]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #12519 from keszybz/man-on-demand
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 20 May 2019 23:25:26 +0000 (08:25 +0900)
committerGitHub <noreply@github.com>
Mon, 20 May 2019 23:25:26 +0000 (08:25 +0900)
Build man pages on demand only

175 files changed:
.travis.yml
README.md
TODO
azure-pipelines.yml [new file with mode: 0644]
catalog/systemd.it.catalog.in
coccinelle/sd_event_source_disable_unref.cocci [new file with mode: 0644]
docs/UIDS-GIDS.md
hwdb/60-keyboard.hwdb
man/bootctl.xml
man/journalctl.xml
man/rules/meson.build
man/sd_bus_set_description.xml
man/sd_bus_slot_set_description.xml
man/sd_event_source_unref.xml
man/systemd-nspawn.xml
man/systemd-udevd.service.xml
man/systemd.journal-fields.xml
man/systemd.link.xml
man/systemd.mount.xml
man/systemd.net-naming-scheme.xml [new file with mode: 0644]
man/systemd.netdev.xml
man/systemd.network.xml
man/systemd.unit.xml
meson.build
po/it.po
semaphoreci/semaphore-runner.sh
src/analyze/analyze.c
src/basic/fs-util.h
src/basic/in-addr-util.c
src/basic/in-addr-util.h
src/basic/linux/README
src/basic/linux/btrfs.h
src/basic/linux/btrfs_tree.h
src/basic/linux/fou.h
src/basic/linux/if.h
src/basic/linux/if_bonding.h
src/basic/linux/if_ether.h
src/basic/linux/if_link.h
src/basic/linux/if_tun.h
src/basic/linux/in.h
src/basic/linux/in6.h
src/basic/linux/update.sh [new file with mode: 0755]
src/basic/process-util.c
src/basic/process-util.h
src/basic/random-util.c
src/basic/socket-util.h
src/basic/terminal-util.c
src/basic/terminal-util.h
src/boot/bootctl.c
src/core/manager.c
src/core/meson.build
src/core/service.c
src/core/timer.c
src/fuzz/fuzz-varlink.c [new file with mode: 0644]
src/fuzz/meson.build
src/import/curl-util.c
src/journal-remote/journal-remote-main.c
src/journal/journal-file.c
src/journal/journal-verify.c
src/journal/journalctl.c
src/journal/journald-server.c
src/journal/journald-server.h
src/libsystemd-network/sd-dhcp-client.c
src/libsystemd-network/test-dhcp-client.c
src/libsystemd/libsystemd.sym
src/libsystemd/sd-event/sd-event.c
src/libsystemd/sd-netlink/netlink-types.c
src/libsystemd/sd-netlink/netlink-types.h
src/network/meson.build
src/network/netdev/bond.c
src/network/netdev/bond.h
src/network/netdev/bridge.c
src/network/netdev/bridge.h
src/network/netdev/fou-tunnel.c
src/network/netdev/fou-tunnel.h
src/network/netdev/geneve.c
src/network/netdev/geneve.h
src/network/netdev/ipvlan.c
src/network/netdev/ipvlan.h
src/network/netdev/l2tp-tunnel.c
src/network/netdev/l2tp-tunnel.h
src/network/netdev/macsec.c
src/network/netdev/macsec.h
src/network/netdev/netdev-gperf.gperf
src/network/netdev/netdev.c
src/network/netdev/netdev.h
src/network/netdev/tunnel.c
src/network/netdev/tuntap.c
src/network/netdev/vcan.h
src/network/netdev/veth.c
src/network/netdev/vlan.c
src/network/netdev/vxlan.c
src/network/netdev/vxlan.h
src/network/netdev/wireguard.c
src/network/netdev/wireguard.h
src/network/networkd-can.c [new file with mode: 0644]
src/network/networkd-can.h [new file with mode: 0644]
src/network/networkd-dhcp4.c
src/network/networkd-dhcp6.c
src/network/networkd-fdb.c
src/network/networkd-fdb.h
src/network/networkd-ipv4ll.c
src/network/networkd-ipv6-proxy-ndp.c
src/network/networkd-link.c
src/network/networkd-link.h
src/network/networkd-lldp-rx.c [new file with mode: 0644]
src/network/networkd-lldp-rx.h [new file with mode: 0644]
src/network/networkd-lldp-tx.c
src/network/networkd-lldp-tx.h
src/network/networkd-manager.c
src/network/networkd-manager.h
src/network/networkd-ndisc.c
src/network/networkd-ndisc.h
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/network/networkd-route.c
src/network/networkd-route.h
src/network/networkd-routing-policy-rule.h
src/network/networkd.c
src/network/test-network.c
src/network/wait-online/manager.c
src/shared/ask-password-api.c
src/shared/efivars.c
src/shared/json.c
src/shared/meson.build
src/shared/sleep-config.c
src/shared/varlink.c [new file with mode: 0644]
src/shared/varlink.h [new file with mode: 0644]
src/shutdown/shutdown.c
src/sleep/sleep.c
src/systemd/sd-dhcp-client.h
src/systemd/sd-event.h
src/systemd/sd-netlink.h
src/test/meson.build
src/test/test-alloc-util.c
src/test/test-terminal-util.c
src/test/test-varlink.c [new file with mode: 0644]
src/udev/net/naming-scheme.h
src/udev/udev-builtin-net_id.c
src/udev/udev-event.c
src/udev/udevd.c
src/vconsole/vconsole-setup.c
sysctl.d/50-default.conf
sysctl.d/50-pid-max.conf [new file with mode: 0644]
sysctl.d/meson.build
test/TEST-32-OOMPOLICY/Makefile [moved from test/TEST-31-OOMPOLICY/Makefile with 100% similarity]
test/TEST-32-OOMPOLICY/test.sh [moved from test/TEST-31-OOMPOLICY/test.sh with 92% similarity]
test/TEST-32-OOMPOLICY/testsuite.sh [moved from test/TEST-31-OOMPOLICY/testsuite.sh with 91% similarity]
test/fuzz/fuzz-netdev-parser/directives.netdev
test/fuzz/fuzz-network-parser/directives.network
test/fuzz/fuzz-varlink/array [new file with mode: 0644]
test/fuzz/fuzz-varlink/do-something [new file with mode: 0644]
test/fuzz/fuzz-varlink/huge-method [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-call [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-error [new file with mode: 0644]
test/fuzz/fuzz-varlink/method-reply [new file with mode: 0644]
test/fuzz/fuzz-varlink/oss-fuzz-14688 [new file with mode: 0644]
test/fuzz/fuzz-varlink/oss-fuzz-14708 [new file with mode: 0644]
test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf [new file with mode: 0644]
test/test-functions
test/test-network/conf/25-ipvtap.netdev [new file with mode: 0644]
test/test-network/conf/25-route-static.network
test/test-network/conf/25-tunnel-local-any.network [new file with mode: 0644]
test/test-network/conf/25-tunnel-remote-any.network [new file with mode: 0644]
test/test-network/conf/25-tunnel.network [new file with mode: 0644]
test/test-network/conf/dhcp-client-ipv6-only.network
test/test-network/conf/ipvtap.network [new file with mode: 0644]
test/test-network/systemd-networkd-tests.py
tmpfiles.d/meson.build
tools/meson-vcs-tag.sh
tools/oss-fuzz.sh
travis-ci/managers/fuzzbuzz.sh
travis-ci/managers/xenial.sh
units/systemd-journal-flush.service.in

index 1dfdc5b799c540b10ada720116441c1951863e37..ab6fe298c768d937444ed4cd56aacb1ab7cd77e0 100644 (file)
@@ -91,20 +91,6 @@ jobs:
           after_script:
               - $CI_MANAGERS/debian.sh CLEANUP
 
-        - name: Ubuntu Xenial
-          language: bash
-          script:
-              - set -e
-              - sudo $CI_MANAGERS/xenial.sh
-              - set +e
-
-        - name: FuzzBuzz
-          language: bash
-          script:
-              - set -e
-              - $CI_MANAGERS/fuzzbuzz.sh
-              - set +e
-
         - stage: Coverity
           language: bash
           env:
index 31d530733aa88ce282e1ced58574735f16f8a5bd..5ed7cfceac9dec55a9e2ef58e25e7f16382b43e1 100644 (file)
--- a/README.md
+++ b/README.md
@@ -3,10 +3,12 @@
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-issues.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-issues-small.svg" alt="Count of open issues over time"></a>
 <a href="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests.svg"><img align="right" src="https://in.waw.pl/systemd-github-state/systemd-systemd-pull-requests-small.svg" alt="Count of open pull requests over time"></a>
 [![Semaphore CI Build Status](https://semaphoreci.com/api/v1/projects/28a5a3ca-3c56-4078-8b5e-7ed6ef912e14/443470/shields_badge.svg)](https://semaphoreci.com/systemd/systemd)<br/>
+[![Coverity Scan Status](https://scan.coverity.com/projects/350/badge.svg)](https://scan.coverity.com/projects/350)<br/>
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1369/badge)](https://bestpractices.coreinfrastructure.org/projects/1369)<br/>
 [![Travis CI Build Status](https://travis-ci.org/systemd/systemd.svg?branch=master)](https://travis-ci.org/systemd/systemd)<br/>
 [![Language Grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/systemd/systemd.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/systemd/systemd/context:cpp)<br/>
-[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)
+[![CentOS CI Build Status](https://ci.centos.org/buildStatus/icon?job=systemd-pr-build)](https://ci.centos.org/job/systemd-pr-build/)<br/>
+[![Build Status](https://dev.azure.com/evvers/systemd-systemd/_apis/build/status/systemd.systemd?branchName=master)](https://dev.azure.com/evvers/systemd-systemd/_build/latest?definitionId=1&branchName=master)
 
 ## Details
 
diff --git a/TODO b/TODO
index 4577c93612a5c160c277315dd765bd25322efe2e..d87a70a0b5327a5cd6a78a1e44261103cc712def 100644 (file)
--- a/TODO
+++ b/TODO
@@ -19,6 +19,9 @@ Janitorial Clean-ups:
 
 Features:
 
+* when killing due to service watchdog timeout maybe detect whether target
+  process is under ptracing and then log loudly and continue instead.
+
 * tweak journald context caching. In addition to caching per-process attributes
   keyed by PID, cache per-cgroup attributes (i.e. the various xattrs we read)
   keyed by cgroup path, and guarded by ctime changes. This should provide us
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644 (file)
index 0000000..9a50e2e
--- /dev/null
@@ -0,0 +1,27 @@
+trigger:
+- master
+
+jobs:
+- job: FuzzBuzz
+  displayName: FuzzBuzz
+
+  pool:
+    vmImage: 'ubuntu-latest'
+
+  steps:
+  - script: |
+      set -e
+      ./travis-ci/managers/fuzzbuzz.sh
+    displayName: 'This is where it gets darker'
+
+- job: ASan_UBSan
+  displayName: ASan_UBSan
+
+  pool:
+    vmImage: 'ubuntu-latest'
+
+  steps:
+  - script: |
+      set -e
+      sudo ./travis-ci/managers/xenial.sh
+    displayName: 'This is where it gets darker'
index 442132efeb7a5d885c2ddd097a64a3d46ffb5bfe..c1375cca3ef228049c32f83244bf4364315c5768 100644 (file)
@@ -34,8 +34,8 @@ Support: %SUPPORT_URL%
 
 @JOURNAL_NAME@ (@JOURNAL_PATH@) sta attualmente utilizzando @CURRENT_USE_PRETTY@.
 L'utilizzo massimo consentito Ã¨ impostato a @MAX_USE_PRETTY@.
-Lasciando liberi almeno @DISK_KEEP_FREE_PRETTY@ (attuale spazio libero: @DISK_AVAILABLE_PRETTY@).
-Il limite di utilizzo forzato Ã¨ quindi @LIMIT_PRETTY@, del quale @AVAILABLE_PRETTY@ sono ancora disponibili.
+Si lasciano liberi almeno @DISK_KEEP_FREE_PRETTY@ (attuale spazio libero: @DISK_AVAILABLE_PRETTY@).
+Il limite di utilizzo forzato Ã¨ quindi @LIMIT_PRETTY@, con @AVAILABLE_PRETTY@ ancora disponibili.
 
 I limiti di controllo dello spazio disco utilizzati dal Journal possono
 essere configurati con le impostazioni SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=,
@@ -164,7 +164,7 @@ L'avvio dello userspace ha richiesto @USERSPACE_USEC@ microsecondi.
 
 # Subject: User manager start-up is now complete
 -- eed00a68ffd84e31882105fd973abdd1
-Subject: User manager start-up is now complete
+Subject: L'istanza di gestione per l'utente Ã¨ completata
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
@@ -245,19 +245,19 @@ Il risultato Ã¨ @JOB_RESULT@.
 
 # Subject: Unit @UNIT@ has begun with reloading its configuration
 -- d34d037fff1847e6ae669a370e694725
-Subject: L'unità @UNIT@ Ã¨ iniziata con il caricamento della propria configurazione
+Subject: L'unità @UNIT@ Ã¨ iniziata con il ricaricamento della propria configurazione
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-L'unità @UNIT@ Ã¨ iniziata con il caricamento della propria configurazione
+L'unità @UNIT@ Ã¨ iniziata con il ricaricamento della propria configurazione
 
 # Subject: Unit @UNIT@ has finished reloading its configuration
 -- 7b05ebc668384222baa8881179cfda54
-Subject: L'unità @UNIT@ Ã¨ terminata dopo aver caricato la propria configurazione
+Subject: L'unità @UNIT@ Ã¨ terminata con il ricaricamento della propria configurazione
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-L'unità @UNIT@ Ã¨ terminata dopo aver caricato la propria configurazione
+L'unità @UNIT@ Ã¨ terminata con il ricaricamento della propria configurazione
 
 Il risultato Ã¨ @JOB_RESULT@.
 
@@ -309,7 +309,7 @@ Subject: Terminata macchina virtuale o container
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-La macchina virtuale @NAME@ con PID primario @LEADER@ Ã¨ stata spenta.
+La macchina virtuale @NAME@ con PID primario @LEADER@ Ã¨ stata terminata.
 
 # Subject: DNSSEC mode has been turned off, as server doesn't support it
 -- 36db2dfa5a9045e1bd4af5f93e1cf057
@@ -319,8 +319,8 @@ Support: %SUPPORT_URL%
 Documentation: man:systemd-resolved.service(8) resolved.conf(5)
 
 Il servizio di risoluzione (systemd-resolved.service) ha rilevato che il
-server DNS indicato non supporta DNSSEC e la validazione DNSSEC Ã¨ stata
-conseguentemente disabilitata.
+server DNS indicato non supporta DNSSEC e la validazione di quest'ultimo tipo
+è stata conseguentemente disabilitata.
 
 Ciò avverrà se DNSSEC=allow-downgrade Ã¨ configurato nel file
 resolved.conf e il server DNS indicato Ã¨ incompatibile con DNSSEC. 
@@ -328,8 +328,8 @@ In questo modo ci si espone ad attacchi "DNSSEC downgrade", e un aggressore
 potrebbe disabilitare la validazione DNSSEC sul sistema inserendo risposte
 DNS nel canale di comunicazione.
 
-Questo evento potrebbe essere indice che il DNS server Ã¨ forse incompatibile
-con DNSSEC o che un aggressore Ã¨ riuscito nel suo intento malevolo.
+Questo evento potrebbe indicare un'incompatibilità del DNS Server con DNSSEC o
+che un aggressore Ã¨ riuscito nel suo intento malevolo.
 
 # Subject: DNSSEC validation failed
 -- 1675d7f172174098b1108bf8c7dc8f5d
@@ -376,7 +376,7 @@ Subject: Unità terminata
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-Unità @UNIT@ entrata con successo nello stato 'dead'.
+Unità @UNIT@ entrata con successo nello stato 'dead' (morto).
 
 # Subject: Unit failed
 -- d9b373ed55a64feb8242e02dbe79a49c
@@ -384,11 +384,11 @@ Subject: Unit fallita
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
-Unità @UNIT@ entrata nello stato 'fallito' con risultato '@UNIT_RESULT@'.
+Unità @UNIT@ entrata nello stato 'failed' (fallito) con risultato '@UNIT_RESULT@'.
 
 # Subject: Unit process exited
 -- 98e322203f7a4ed290d09fe03c09fe15
-Subject: Terminato processo unità
+Subject: Uscito processo unità
 Defined-By: systemd
 Support: %SUPPORT_URL%
 
@@ -420,8 +420,8 @@ Defined-By: systemd
 Support: %SUPPORT_URL%
 
 Un processo dell'unità @UNIT@ Ã¨ stato terminato dalla logica del kernel Linux per
-gestire gli eventi out-of-memory (OOM). Questo usualmente indica che il sistema ha
-poca memoria e questa dovrebbe essere liberata. Un processo associato con @UNIT@ Ã¨
+gestire gli eventi out-of-memory (OOM). In altri termini, il sistema ha
+poca memoria e dovrebbe essere liberata. Un processo associato con @UNIT@ Ã¨
 stato identificato come il processo ideale da terminare e così Ã¨ stato.
 
 La pressione sulla memoira potrebbe o meno essere causata da @UNIT@.
diff --git a/coccinelle/sd_event_source_disable_unref.cocci b/coccinelle/sd_event_source_disable_unref.cocci
new file mode 100644 (file)
index 0000000..2763fef
--- /dev/null
@@ -0,0 +1,36 @@
+@@
+expression p;
+@@
+- if (p) {
+-         (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         p = sd_event_source_unref(p);
+- }
++ p = sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+-         sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- if (p) {
+-         (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+-         sd_event_source_unref(p);
+- }
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- (void) sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
+@@
+expression p;
+@@
+- sd_event_source_set_enabled(p, SD_EVENT_OFF);
+- sd_event_source_unref(p);
++ sd_event_source_disable_unref(p);
index 25345a918f65a733a3e6750889e3810b8e022eda..480ee231e74319e1cc331133965a62cc49a6094b 100644 (file)
@@ -237,7 +237,8 @@ the artifacts the container manager persistently leaves in the system.
 |                 65535 | 16bit `(uid_t) -1`    | Linux         |                               |
 |          65536…524287 | Unused                |               |                               |
 |     524288…1879048191 | Container UID ranges  | `systemd`     | `nss-mymachines`              |
-| 1879048192…4294967294 | Unused                |               |                               |
+| 1879048191…2147483647 | Unused                |               |                               |
+| 2147483648…4294967294 | HIC SVNT LEONES       |               |                               |
 |            4294967295 | 32bit `(uid_t) -1`    | Linux         |                               |
 
 Note that "Unused" in the table above doesn't meant that these ranges are
@@ -246,6 +247,13 @@ pre-defined purposes between Linux, generic low-level distributions and
 `systemd`. There might very well be other packages that allocate from these
 ranges.
 
+Note that the range 2147483648…4294967294 (i.e. 2^31…2^32-2) should be handled
+with care. Various programs (including kernel file systems, see `devpts`) have
+trouble with UIDs outside of the signed 32bit range, i.e any UIDs equal to or
+above 2147483648. It is thus strongly recommended to stay away from this range
+in order to avoid complications. This range should be considered reserved for
+future, special purposes.
+
 ## Notes on resolvability of user and group names
 
 User names, UIDs, group names and GIDs don't have to be resolvable using NSS
index a05db181b82812f4ef7855b9bb5f2ef8e6a79e62..62957d27250712a5007ea7ddf2bcbe93befb0b57 100644 (file)
@@ -847,23 +847,39 @@ evdev:input:b0003v04B3p301B*
 evdev:input:b0003v046Dp00*
  KEYBOARD_KEY_c0183=media           # HUT:config, kbd:Media/Music player button
  KEYBOARD_KEY_c1001=chat            # Messenger button
+ KEYBOARD_KEY_c1002=camera          # Webcam button
  KEYBOARD_KEY_c1003=audio           # Music Browser button
  KEYBOARD_KEY_c1004=video           # Video Browser button
  KEYBOARD_KEY_c1005=images          # Image Browser button
  KEYBOARD_KEY_c100a=documents       # Document Browser button
+ KEYBOARD_KEY_c100b=rewind          # Rewind button
+ KEYBOARD_KEY_c100c=fastforward     # Fast Forward button
+ KEYBOARD_KEY_c100f=f14             # Track 1 button â†’ f14 â†’ XF86Launch5
+ KEYBOARD_KEY_c1010=f15             # Track 2 button â†’ f15 â†’ XF86Launch6
+ KEYBOARD_KEY_c1011=channeldown     # Playlist back button
+ KEYBOARD_KEY_c1012=channelup       # Playlist advance button
  KEYBOARD_KEY_c1013=camera          # Webcam button
  KEYBOARD_KEY_c1014=coffee          # Status button
  KEYBOARD_KEY_c1015=record          # Record symbol button
  KEYBOARD_KEY_c1016=sound           # Flame/CD burning â†’ sound â†’ XF86AudioPreset
  KEYBOARD_KEY_c1017=ejectcd         # Eject button
  KEYBOARD_KEY_c1018=config          # Remote-control ico
+ KEYBOARD_KEY_c1019=f14             # Preset 1 â†’ f14 â†’ XF86Launch5
+ KEYBOARD_KEY_c101a=f15             # Preset 2 â†’ f15 â†’ XF86Launch6
+ KEYBOARD_KEY_c101b=f16             # Preset 3 â†’ f16 â†’ XF86Launch7
  KEYBOARD_KEY_c101c=cyclewindows    # 2 overlapping windows icon
  KEYBOARD_KEY_c101f=zoomout         # zoom - button / - side of zoomrocker
  KEYBOARD_KEY_c1020=zoomin          # zoom + button / + side off zoom rocker
  KEYBOARD_KEY_c1021=zoomreset       # 100% symbol on kbd left side
  KEYBOARD_KEY_c1023=close           # [x] symbol on kbd left side
+ KEYBOARD_KEY_c1027=menu            # Hamburger menu icon
+ KEYBOARD_KEY_c1028=angle           # Rotate button
  KEYBOARD_KEY_c1029=shuffle         # Shuffle button
+ KEYBOARD_KEY_c102a=back            # Back button
+ KEYBOARD_KEY_c102b=cyclewindows    # Empty window icon
  KEYBOARD_KEY_c102d=www             # www text + magnifierglass icon
+ KEYBOARD_KEY_c1031=connect         # Pickup phone button â†’ connect â†’ XF86Go
+ KEYBOARD_KEY_c1032=cancel          # Hangup phone button â†’ cancel â†’ Cancel
  KEYBOARD_KEY_c1041=help            # Help text or icon (Fn + F1)
  KEYBOARD_KEY_c1042=wordprocessor   # Word icon (Fn + F2)
  KEYBOARD_KEY_c1043=spreadsheet     # Excel icon (Fn + F3)
@@ -879,7 +895,6 @@ evdev:input:b0003v046Dp00*
 
 # Cordless Access Keyboard (27 MHz, modelnumber Y-RH35)
 evdev:input:b0003v046Dp0042*
- KEYBOARD_KEY_c1002=camera
  KEYBOARD_KEY_c1041=new
  KEYBOARD_KEY_c1042=reply
  KEYBOARD_KEY_c1043=forward
@@ -904,6 +919,10 @@ evdev:input:b0003v046Dp0045*
  KEYBOARD_KEY_c104b=images
  KEYBOARD_KEY_c104c=audio
 
+# S510 keyboard (27 MHz, modelnumber Y-RAK73)
+evdev:input:b0003v046Dp0056*
+ KEYBOARD_KEY_c1041=battery      # Battery icon (Fn + F1)
+
 # MX3000 keyboard (27 MHz, modelnumber Y-RAM74)
 # We ignore the scroll up / down keypress events since these buttons also
 # generate scroll-wheel events and we do not want to generate duplicate events
@@ -911,11 +930,6 @@ evdev:input:b0003v046Dp0045*
 # cleared then the scroll-wheel events for these buttons go away and then
 # tilting the scrollwheel left/right starts sending c1022 / c1024 events
 evdev:input:b0003v046Dp0057*
- KEYBOARD_KEY_c1011=channeldown  # Playlist back button
- KEYBOARD_KEY_c1012=channelup    # Playlist advance button
- KEYBOARD_KEY_c1019=f14          # Preset 1 â†’ f14 â†’ XF86Launch5
- KEYBOARD_KEY_c101a=f15          # Preset 2 â†’ f15 â†’ XF86Launch6
- KEYBOARD_KEY_c101b=f16          # Preset 3 â†’ f16 â†’ XF86Launch7
  KEYBOARD_KEY_c1041=battery      # Battery icon (Fn + F1)
 
 #KEYBOARD_KEY_c101d=scrolldown   # Button below scrollwheel (see note above)
@@ -926,11 +940,7 @@ evdev:input:b0003v046Dp0057*
 # MX3200 keyboard (27 MHz, modelnumber Y-RAV80)
 evdev:input:b0003v046Dp005C*
  KEYBOARD_KEY_c1001=phone           # VOIP button
- KEYBOARD_KEY_c100f=f14             # Track 1 button â†’ f14 â†’ XF86Launch5
- KEYBOARD_KEY_c1010=f15             # Track 2 button â†’ f15 â†’ XF86Launch6
  KEYBOARD_KEY_c1016=record          # Record button
- KEYBOARD_KEY_c1031=connect         # Pickup phone button â†’ connect â†’ XF86Go
- KEYBOARD_KEY_c1032=cancel          # Hangup phone button â†’ cancel â†’ Cancel
  KEYBOARD_KEY_c1041=wordprocessor   # Word icon (Fn + F1)
  KEYBOARD_KEY_c1042=spreadsheet     # Excel icon (Fn + F2)
  KEYBOARD_KEY_c1043=calendar        # Calendar icon (Fn + F3)
@@ -962,6 +972,10 @@ evdev:input:b0003v046Dp0066*
  KEYBOARD_KEY_c1048=config          # Window with gear icon (Fn + F8)
  KEYBOARD_KEY_c106f=battery         # Battery icon
 
+# S510 remote control (27 MHz)
+evdev:input:b0003v046Dp00FE*
+ KEYBOARD_KEY_c1018=media           # Media button
+
 # MX5000 keyboard (HID proxy mode and bluetooth matches)
 # The 4 buttons below the LCD send codes 0xc100c - 0xc100f. They only send
 # these codes when the LCD is displaying text send to it. These codes are
index a80a37309c9f0022661238986afbf52ee67b684d..46b9738b148acc4a9a08752c8c2373b0a1340df5 100644 (file)
       <varlistentry>
         <term><option>-p</option></term>
         <term><option>--print-esp-path</option></term>
-        <listitem><para>This option modifies the behaviour of <command>status</command>.  Prints only the
-        path to the EFI System Partition (ESP) to standard output and exits.</para></listitem>
+        <listitem><para>This option modifies the behaviour of <command>status</command>. Only prints the path
+        to the EFI System Partition (ESP) to standard output and exits.</para></listitem>
       </varlistentry>
 
       <varlistentry>
+        <term><option>-x</option></term>
         <term><option>--print-boot-path</option></term>
-        <listitem><para>This option modifies the behaviour of <command>status</command>.  Prints only the
-        path to the Extended Boot Loader partition if it exists, and the path to the ESP otherwise to
-        standard output and exit. This command is useful to determine where to place boot loader entries, as
-        they are preferably placed in the Extended Boot Loader partition if it exists and in the ESP
-        otherwise.</para></listitem>
+        <listitem><para>This option modifies the behaviour of <command>status</command>. Only prints the path
+        to the Extended Boot Loader partition if it exists, and the path to the ESP otherwise to standard
+        output and exit. This command is useful to determine where to place boot loader entries, as they are
+        preferably placed in the Extended Boot Loader partition if it exists and in the ESP otherwise.
+        </para></listitem>
       </varlistentry>
 
       <varlistentry>
index a3c67f5e82d1335fced6908f36d6209eaf2fdbf9..0ecab521fa0aae8f18f6e16db126ed7e1a217465 100644 (file)
       <varlistentry>
         <term><option>--flush</option></term>
 
-        <listitem><para>Asks the journal daemon to flush any log data
-        stored in <filename>/run/log/journal</filename> into
-        <filename>/var/log/journal</filename>, if persistent storage
-        is enabled. This call does not return until the operation is
-        complete. Note that this call is idempotent: the data is only
-        flushed from <filename>/run/log/journal</filename> into
-        <filename>/var/log/journal</filename> once during system
-        runtime, and this command exits cleanly without executing any
-        operation if this has already happened. This command
-        effectively guarantees that all data is flushed to
-        <filename>/var/log/journal</filename> at the time it
-        returns.</para></listitem>
+        <listitem><para>Asks the journal daemon to flush any log data stored in
+        <filename>/run/log/journal/</filename> into <filename>/var/log/journal/</filename>, if persistent
+        storage is enabled. This call does not return until the operation is complete. Note that this call is
+        idempotent: the data is only flushed from <filename>/run/log/journal/</filename> into
+        <filename>/var/log/journal</filename> once during system runtime (but see
+        <option>--relinquish-var</option> below), and this command exits cleanly without executing any
+        operation if this has already happened. This command effectively guarantees that all data is flushed
+        to <filename>/var/log/journal</filename> at the time it returns.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--relinquish-var</option></term>
+
+        <listitem><para>Asks the journal daemon for the reverse operation to <option>--flush</option>: if
+        requested the daemon will write further log data to <filename>/run/log/journal/</filename> and stops
+        writing to <filename>/var/log/journal/</filename>. A subsequent call to <option>--flush</option>
+        causes the log output to switch back to <filename>/var/log/journal/</filename>, see
+        above.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--smart-relinquish-var</option></term>
+
+        <listitem><para>Similar to <option>--relinquish-var</option> but executes no operation if the root file
+        system and <filename>/var/lib/journal/</filename> reside on the same mount point. This operation is
+        used during system shutdown in order to make the journal daemon stop writing data to
+        <filename>/var/log/journal/</filename> in case that directory is located on a mount point that needs
+        to be unmounted.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 689415846642c523fbbec7e014d13bde84095da4..6d47f09f48f9ee302520f941eaaeda3c8a6fa660 100644 (file)
@@ -445,7 +445,10 @@ manpages = [
  ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''],
  ['sd_event_source_unref',
   '3',
-  ['sd_event_source_ref', 'sd_event_source_unrefp'],
+  ['sd_event_source_disable_unref',
+   'sd_event_source_disable_unrefp',
+   'sd_event_source_ref',
+   'sd_event_source_unrefp'],
   ''],
  ['sd_event_wait',
   '3',
@@ -824,6 +827,7 @@ manpages = [
  ['systemd.kill', '5', [], ''],
  ['systemd.link', '5', [], ''],
  ['systemd.mount', '5', [], ''],
+ ['systemd.net-naming-scheme', '7', [], ''],
  ['systemd.netdev', '5', [], 'ENABLE_NETWORKD'],
  ['systemd.network', '5', [], 'ENABLE_NETWORKD'],
  ['systemd.nspawn', '5', [], ''],
index cfcebdfb29eb79472d38b209c432b15120078adb..3c5580e27cace84a2c879154dbbfaef9220b9404 100644 (file)
 
           <listitem><para>An argument is invalid.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOPKG</constant></term>
 
           <listitem><para>The bus cannot be resolved.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-EPERM</constant></term>
 
           <listitem><para>The bus has already been started.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ECHILD</constant></term>
 
           <listitem><para>The bus was created in a different process.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOMEM</constant></term>
 
index 13dd6f8815820cb943de540e624f3b1fc0294f92..9bc2ba859257299903542697b3889ca16b6fa820 100644 (file)
 
           <listitem><para>An required argument is <constant>NULL</constant>.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENXIO</constant></term>
 
           <listitem><para>The bus slot object has no description.</para></listitem>
         </varlistentry>
-      </variablelist>
 
-      <variablelist>
         <varlistentry>
           <term><constant>-ENOMEM</constant></term>
 
index 01e3008eed4a94e87bc95216f72d0035a3bcfc53..81131fa737f373b8f85612dc75d0b8212a5bbbad 100644 (file)
@@ -19,6 +19,8 @@
     <refname>sd_event_source_unref</refname>
     <refname>sd_event_source_unrefp</refname>
     <refname>sd_event_source_ref</refname>
+    <refname>sd_event_source_disable_unref</refname>
+    <refname>sd_event_source_disable_unrefp</refname>
 
     <refpurpose>Increase or decrease event source reference counters</refpurpose>
   </refnamediv>
         <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
       </funcprototype>
 
+      <funcprototype>
+        <funcdef>sd_event_source* <function>sd_event_source_disable_unref</function></funcdef>
+        <paramdef>sd_event_source *<parameter>source</parameter></paramdef>
+      </funcprototype>
+
+      <funcprototype>
+        <funcdef>void <function>sd_event_source_disable_unrefp</function></funcdef>
+        <paramdef>sd_event_source **<parameter>source</parameter></paramdef>
+      </funcprototype>
     </funcsynopsis>
   </refsynopsisdiv>
 
     the passed event source object is
     <constant>NULL</constant>.</para>
 
-    <para>Note that event source objects stay alive and may be
-    dispatched as long as they have a reference counter greater than
-    zero. In order to drop a reference of an event source and make
-    sure the associated event source handler function is not called
-    anymore it is recommended to combine a call of
+    <para>Note that event source objects stay alive and may be dispatched as long as they have a reference
+    counter greater than zero. In order to drop a reference of an event source and make sure the associated
+    event source handler function is not called anymore it is recommended to combine a call of
     <function>sd_event_source_unref()</function> with a prior call to
-    <function>sd_event_source_set_enabled()</function> with
-    <constant>SD_EVENT_OFF</constant>.</para>
+    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> or call
+    <function>sd_event_source_disable_unref()</function>, see below.</para>
+
+    <para><function>sd_event_source_disable_unref()</function> combines a call to
+    <function>sd_event_source_set_enabled()</function> with <constant>SD_EVENT_OFF</constant> with
+    <function>sd_event_source_unref()</function>. This ensures that the source is disabled before the local
+    reference to it is lost. The <parameter>source</parameter> parameter is allowed to be
+    <constant>NULL</constant>.</para>
+
+    <para><function>sd_event_source_disable_unrefp()</function> is similar to
+    <function>sd_event_source_unrefp()</function>, but in addition disables the source first. This call is
+    useful in conjunction with GCC's and LLVM's
+    <ulink url="https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html">Clean-up Variable
+    Attribute</ulink>. Note that this function is defined as inline function.</para>
   </refsect1>
 
   <refsect1>
     <title>Return Value</title>
 
-    <para><function>sd_event_source_unref()</function> always returns
-    <constant>NULL</constant>.
-    <function>sd_event_source_ref()</function> always returns the
-    event source object passed in.</para>
+    <para><function>sd_event_source_unref()</function> and
+    <function>sd_event_source_disable_unref()</function> always return <constant>NULL</constant>.
+    <function>sd_event_source_ref()</function> always returns the event source object passed in.</para>
   </refsect1>
 
   <xi:include href="libsystemd-pkgconfig.xml" />
index 5ba162b93cadf2fa3a252ddbb19b5b30315fa9d8..f1d6f14812519b6765078d71fcdb17853e4f85c1 100644 (file)
@@ -1,8 +1,8 @@
 <?xml version='1.0'?>
 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
   "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
-<!ENTITY fedora_latest_version "28">
-<!ENTITY fedora_cloud_release "1.1">
+<!ENTITY fedora_latest_version "30">
+<!ENTITY fedora_cloud_release "1.2">
 ]>
 <!-- SPDX-License-Identifier: LGPL-2.1+ -->
 
 
       <programlisting># machinectl pull-raw --verify=no \
       https://download.fedoraproject.org/pub/fedora/linux/releases/&fedora_latest_version;/Cloud/x86_64/images/Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw.xz
-# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64.raw</programlisting>
+# systemd-nspawn -M Fedora-Cloud-Base-&fedora_latest_version;-&fedora_cloud_release;.x86_64</programlisting>
 
       <para>This downloads an image using
       <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
index cf8087ccb3189e094a9a83067312cb604d771010..c267bb2b114b3da1f5154fbb06bf3bf46b286693 100644 (file)
         <term><varname>net.naming-scheme=</varname></term>
         <listitem>
           <para>Network interfaces are renamed to give them predictable names when possible (unless
-          <varname>net.ifnames=0</varname> is specified, see above). The names are derived from various
-          device metadata fields. Newer versions of <filename>systemd-udevd.service</filename> take more of
-          these fields into account, improving (and thus possibly changing) the names used for the same
-          devices. With this kernel command line option it is possible to pick a specific version of this
-          algorithm. It expects a naming scheme identifier as argument. Currently the following identifiers
-          are known: <literal>v238</literal>, <literal>v239</literal>, <literal>v240</literal> which each
-          implement the naming scheme that was the default in the indicated systemd version. In addition,
-          <literal>latest</literal> may be used to designate the latest scheme known (to this particular
-          version of <filename>systemd-udevd.service</filename>).</para>
+          <varname>net.ifnames=0</varname> is specified, see above). With this kernel command line option it
+          is possible to pick a specific version of this algorithm and override the default chosen at
+          compilation time. Expects one of the naming scheme identifiers listed in
+          <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+          or <literal>latest</literal> to select the latest scheme known (to this particular version of
+          <filename>systemd-udevd.service</filename>).</para>
 
           <para>Note that selecting a specific scheme is not sufficient to fully stabilize interface naming:
           the naming is generally derived from driver attributes exposed by the kernel. As the kernel is
         </listitem>
       </varlistentry>
     </variablelist>
-    <!-- when adding entries here, consider also adding them
-         in kernel-command-line.xml -->
- </refsect1>
+    <!-- when adding entries here, consider also adding them in kernel-command-line.xml -->
+  </refsect1>
 
   <refsect1>
     <title>See Also</title>
index 960b2ec6336c576c6c02fc95982f89d1561e262e..fa374bf0f804d1cdc487a8fed111cd00e5c9e274 100644 (file)
           usually derived from glibc's
           <varname>program_invocation_short_name</varname> variable, see
           <citerefentry project='die-net'><refentrytitle>program_invocation_short_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>.)</para>
+          <para>Note that the journal service does not validate the values of any structured
+          journal fields whose name is not prefixed with an underscore, and this includes any
+          syslog related fields such as these. Hence, applications that supply a facility, PID,
+          or log level are expected to do so properly formatted, i.e. as numeric integers formatted
+          as decimal strings.</para>
         </listitem>
       </varlistentry>
 
index ea744bd2517a7d3f829a402a1658f2dfb0aec2cd..b1be32955e5f8aeb5e2688f4c09e38378617484d 100644 (file)
                 <para>The name is set based on information given by
                 the firmware for on-board devices, as exported by the
                 udev property <varname>ID_NET_NAME_ONBOARD</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
                 </para>
               </listitem>
             </varlistentry>
                 <para>The name is set based on information given by
                 the firmware for hot-plug devices, as exported by the
                 udev property <varname>ID_NET_NAME_SLOT</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
                 </para>
               </listitem>
             </varlistentry>
               <listitem>
                 <para>The name is set based on the device's physical
                 location, as exported by the udev property
-                <varname>ID_NET_NAME_PATH</varname>.</para>
+                <varname>ID_NET_NAME_PATH</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+                </para>
               </listitem>
             </varlistentry>
             <varlistentry>
               <listitem>
                 <para>The name is set based on the device's persistent
                 MAC address, as exported by the udev property
-                <varname>ID_NET_NAME_MAC</varname>.</para>
+                <varname>ID_NET_NAME_MAC</varname>.
+                See <citerefentry><refentrytitle>systemd.net-naming-scheme</refentrytitle><manvolnum>7</manvolnum></citerefentry>.
+                </para>
               </listitem>
             </varlistentry>
             <varlistentry>
index 022e227e837ec81d054742b489b0213f1dbf62f6..178dc188a5a2a35ea096cc96b2d0027e398834d0 100644 (file)
     mount options are understood by systemd which influence how
     dependencies are created for mount points. systemd will create a
     dependency of type <varname>Wants=</varname> or
-    <option>Requires</option> (see option <option>nofail</option>
+    <option>Requires=</option> (see option <option>nofail</option>
     below), from either <filename>local-fs.target</filename> or
     <filename>remote-fs.target</filename>, depending whether the file
     system is local or remote.</para>
diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml
new file mode 100644 (file)
index 0000000..eb8faad
--- /dev/null
@@ -0,0 +1,420 @@
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+  "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+<!-- SPDX-License-Identifier: LGPL-2.1+ -->
+
+<refentry id="systemd.net-naming-scheme">
+  <refentryinfo>
+    <title>systemd.net-naming-scheme</title>
+    <productname>systemd</productname>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>systemd.net-naming-scheme</refentrytitle>
+    <manvolnum>7</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>systemd.net-naming-scheme</refname>
+    <refpurpose>Network device naming schemes</refpurpose>
+  </refnamediv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Network interfaces may be renamed to give them predictable names when there's enough information to
+    generate appropriate names and the use of certain types of names is configured. This page describes the
+    first part, i.e. what possible names may be generated. Those names are generated by the
+    <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+    builtin <command>net_id</command> and exported as udev properties
+    (<varname>ID_NET_NAME_ONBOARD=</varname>, <varname>ID_NET_LABEL_ONBOARD=</varname>,
+    <varname>ID_NET_NAME_PATH=</varname>, <varname>ID_NET_NAME_SLOT=</varname>).</para>
+
+    <para>Names are derived from various device metadata attributes. Newer versions of udev take more of
+    these attributes into account, improving (and thus possibly changing) the names used for the same
+    devices. Differents version of the naming rules are called "naming schemes". The default naming scheme is
+    chosen at compilation time. Usually this will be the latest implemented version, but it is also possible
+    to set one of the older versions to preserve compatibility. This may be useful for example for
+    distributions, which may introduce new versions of systemd in stable releases without changing the naming
+    scheme. The naming scheme may also be overriden using the <varname>net.naming-scheme=</varname> kernel
+    command line switch, see
+    <citerefentry><refentrytitle>systemd-udevd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
+    Available naming schemes are described below.</para>
+
+    <para>After the udev proprties have been generated, appropriate udev rules may be used to actually rename
+    devices based on those properties. See the description of <varname>NamePolicy=</varname> in
+    <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Naming</title>
+
+    <para>All names start with a two-character prefix that signifies the interface type.</para>
+
+    <table>
+      <title>Two character prefixes based on the type of interface</title>
+
+      <tgroup cols='2'>
+        <thead>
+          <row>
+            <entry>Prefix</entry>
+            <entry>Description</entry>
+          </row>
+        </thead>
+        <tbody>
+          <row>
+            <entry><constant>en</constant></entry>
+            <entry>Ethernet</entry>
+          </row>
+          <row>
+            <entry><constant>ib</constant></entry>
+            <entry>InfiniBand</entry>
+          </row>
+          <row>
+            <entry><constant>sl</constant></entry>
+            <entry>serial line IP (slip)</entry>
+          </row>
+          <row>
+            <entry><constant>wl</constant></entry>
+            <entry>Wireless local area network (WLAN)</entry>
+          </row>
+          <row>
+            <entry><constant>ww</constant></entry>
+            <entry>Wireless wide area network (WWAN)</entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </table>
+
+    <para>The udev <command>net_id</command> builtin exports the following udev device properties:</para>
+
+    <variablelist>
+        <varlistentry>
+          <term><varname>ID_NET_NAME_ONBOARD=<replaceable>prefix</replaceable><constant>o</constant><replaceable>number</replaceable></varname></term>
+
+          <listitem><para>This name is set based on the ordering information given by the firmware for
+          on-board devices. The name consists of the prefix, letter <constant>o</constant>, and a number
+          specified by the firmware. This is only available for PCI devices.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_LABEL_ONBOARD=<replaceable>prefix</replaceable> <replaceable>label</replaceable></varname></term>
+
+          <listitem><para>This property is set based on label given by the firmware for on-board devices. The
+          name consists of the prefix concatenated with the label. This is only available for PCI devices.
+          </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_MAC=<replaceable>prefix</replaceable><constant>x</constant><replaceable>AABBCCDDEEFF</replaceable></varname></term>
+
+          <listitem><para>This name consists of the prefix, letter <constant>x</constant>, and 12 hexadecimal
+          digits of the MAC address. It is available if the device has a fixed MAC address. Because this name
+          is based on an attribute of the card itself, it remains "stable" when the device is moved (even
+          between machines), but will change when the hardware is replaced.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_SLOT=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>v</constant><replaceable>slot</replaceable></varname></term>
+
+          <listitem><para>This property describes the slot position. Different schemes are used depending on
+          the bus type, as described in the table below. In all cases, PCI slot information must be known. In
+          case of USB, BCMA, and SR-VIO devices, the full name consists of the prefix, PCI slot identifier,
+          and USB or BCMA or SR-VIO slot identifier. The first two parts are denoted as "…" in the table
+          below.</para>
+
+          <table>
+            <title>Slot naming schemes</title>
+
+            <tgroup cols='2'>
+              <thead>
+                <row>
+                  <entry>Format</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+
+              <tbody>
+                <row>
+                  <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
+                  <entry>PCI slot number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
+                  <entry>Broadcom bus (BCMA) core number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
+                  <entry>USB port number chain</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>v</constant><replaceable>slot</replaceable></entry>
+                  <entry>SR-VIO slot number</entry>
+                </row>
+              </tbody>
+            </tgroup>
+          </table>
+
+          <para>The PCI domain is only prepended when it is not 0. All multi-function PCI devices will carry
+          the <constant>f<replaceable>function</replaceable></constant> number in the device name, including
+          the function 0 device. For non-multi-function devices, the number is suppressed if 0. The port name
+          <replaceable>port_name</replaceable> is used, or the port number
+          <constant>d</constant><replaceable>dev_port</replaceable> if the name is not known.</para>
+
+          <para>For BCMA devices, the core number is suppressed when 0.</para>
+
+          <para>For USB devices the full chain of port numbers of hubs is composed. If the name gets longer
+          than the maximum number of 15 characters, the name is not exported. The usual USB configuration
+          number 1 and interface number 0 values are suppressed.</para>
+          </listitem>
+
+          <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
+          <constant>v</constant> and the virtual device number, with any leading zeros removed. The bus
+          number is ignored. This device type is found in IBM PowerVMs.</para>
+        </varlistentry>
+
+        <varlistentry>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>c</constant><replaceable>bus_id</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>a</constant><replaceable>vendor</replaceable><replaceable>model</replaceable><constant>i</constant><replaceable>instance</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable><constant>i</constant><replaceable>address</replaceable><constant>n</constant><replaceable>port_name</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]</varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>b</constant><replaceable>number</replaceable></varname></term>
+          <term><varname>ID_NET_NAME_PATH=<replaceable>prefix</replaceable>[<constant>P</constant><replaceable>domain</replaceable>]<constant>p</constant><replaceable>bus</replaceable><constant>s</constant><replaceable>slot</replaceable>[<constant>f</constant><replaceable>function</replaceable>][<constant>n</constant><replaceable>phys_port_name</replaceable>|<constant>d</constant><replaceable>dev_port</replaceable>]<constant>u</constant><replaceable>port</replaceable>…[<constant>c</constant><replaceable>config</replaceable>][<constant>i</constant><replaceable>interface</replaceable>]</varname></term>
+
+          <listitem><para>This property describes the device installation location. Different schemes are
+          used depending on the bus type, as described in the table below. For BCMA and USB devices, PCI path
+          information must known, and the full name consists of the prefix, PCI slot identifier, and USB or
+          BCMA location. The first two parts are denoted as "…" in the table below.</para>
+
+          <table>
+            <title>Path naming schemes</title>
+
+            <tgroup cols='2'>
+              <thead>
+                <row>
+                  <entry>Format</entry>
+                  <entry>Description</entry>
+                </row>
+              </thead>
+
+              <tbody>
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>c</constant><replaceable>bus_id</replaceable></entry>
+                  <entry>CCW or grouped CCW device identifier</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>a</constant><replaceable>vendor</replaceable> <replaceable>model</replaceable> <constant>i</constant><replaceable>instance</replaceable></entry>
+                  <entry>ACPI path names for ARM64 platform devices</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> <constant>i</constant><replaceable>address</replaceable> <constant>n</constant><replaceable>port_name</replaceable></entry>
+                  <entry>Netdevsim (simulated networking device) device number and port name</entry>
+                </row>
+
+                <row>
+                  <entry><replaceable>prefix</replaceable> [<constant>P</constant><replaceable>domain</replaceable>] <constant>p</constant><replaceable>bus</replaceable> <constant>s</constant><replaceable>slot</replaceable> [<constant>f</constant><replaceable>function</replaceable>] [<constant>n</constant><replaceable>phys_port_name</replaceable> | <constant>d</constant><replaceable>dev_port</replaceable>]</entry>
+                  <entry>PCI geographical location</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>b</constant><replaceable>number</replaceable></entry>
+                  <entry>Broadcom bus (BCMA) core number</entry>
+                </row>
+
+                <row>
+                  <entry>… <constant>u</constant><replaceable>port</replaceable>… [<constant>c</constant><replaceable>config</replaceable>] [<constant>i</constant><replaceable>interface</replaceable>]</entry>
+                  <entry>USB port number chain</entry>
+                </row>
+
+              </tbody>
+            </tgroup>
+          </table>
+
+          <para>CCW and grouped CCW devices are found in IBM System Z mainframes. Any leading zeros and
+          dots are suppressed.</para>
+
+          <para>For PCI, BCMA, and USB devices, the same rules as described above for slot naming are
+          used.</para>
+          </listitem>
+        </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>History</title>
+
+    <para>The following "naming schemes" have been defined:</para>
+
+    <variablelist>
+        <varlistentry>
+          <term><constant>v238</constant></term>
+
+          <listitem><para>This is the naming naming that was implemented in systemd 238.</para></listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v239</constant></term>
+
+          <listitem><para>Naming was changed for virtual network interfaces created with SR-IOV and NPAR and
+          for devices where the PCI network controller device does not have a slot number associated.</para>
+
+          <para>SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of
+          <literal>v<replaceable>port</replaceable></literal>, where <replaceable>port</replaceable> is the
+          virtual device number. Previously those virtual devices were named as if completely independent.
+          </para>
+
+          <para>The ninth and later NPAR virtual devices are named following the scheme used for the first
+          eight NPAR partitions. Previously those devices were not renamed and the kernel default
+          ("eth<replaceable>N</replaceable>") was used.</para>
+
+          <para>Names are also generated for PCI devices where the PCI network controller device does not
+          have an associated slot number itself, but one of its parents does. Previously those devices were
+          not renamed and the kernel default was used.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v240</constant></term>
+
+          <para>The <literal>ib</literal> prefix and stable names for infiniband devices are
+          introduced. Previously those devices were not renamed.</para>
+
+          <para>The ACPI index field (used in <varname>ID_NET_NAME_ONBOARD=</varname>) is now also used when
+          0.</para>
+
+          <para>A new naming policy <varname>NamePolicy=keep</varname> was introduced. With this policy, if
+          the network device name was already set by userspace, the device will not be renamed
+          again. Previously, this naming policy applied implicitly, and now it must be explicitly
+          requested. Effectively, this means that network devices will be renamed according to the
+          configuration, even if they have been renamed already, if <constant>keep</constant> is not
+          specified as the naming policy in the <filename noindex='true'>.link</filename> file. See
+          <citerefentry><refentrytitle>systemd.link</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+          for a description of <varname>NamePolicy=</varname>.</para>
+        </varlistentry>
+
+        <varlistentry>
+          <term><constant>v243</constant></term>
+
+          <para>Support for netdevsim (simulated networking devices) was added. Previously those devices were
+          not renamed.</para>
+
+          <para>Previously two-letter interface type prefix was prepended to
+          <varname>ID_NET_LABEL_ONBOARD=</varname>. This is not done anymore.</para>
+        </varlistentry>
+
+        <para>Note that <constant>latest</constant> may be used to denote the latest scheme known (to this
+        particular version of systemd.</para>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Examples</title>
+
+    <example>
+      <title>Using <command>udevadm test-builtin</command> to display device properties</title>
+
+      <programlisting>$ udevadm test-builtin net_id /sys/class/net/enp0s31f6
+...
+Using default interface naming scheme 'v243'.
+ID_NET_NAMING_SCHEME=v243
+ID_NET_NAME_MAC=enx54ee75cb1dc0
+ID_OUI_FROM_DATABASE=Wistron InfoComm(Kunshan)Co.,Ltd.
+ID_NET_NAME_PATH=enp0s31f6
+...</programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet card with firmware index "1"</title>
+
+      <programlisting>ID_NET_NAME_ONBOARD=eno1
+ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
+      </programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet card in hotplug slot with firmware index number</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
+ID_NET_NAME_MAC=enx000000000466
+ID_NET_NAME_PATH=enp5s0
+ID_NET_NAME_SLOT=ens1</programlisting>
+    </example>
+
+    <example>
+      <title>PCI Ethernet multi-function card with 2 ports</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
+ID_NET_NAME_MAC=enx78e7d1ea46da
+ID_NET_NAME_PATH=enp2s0f0
+
+# /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
+ID_NET_NAME_MAC=enx78e7d1ea46dc
+ID_NET_NAME_PATH=enp2s0f1</programlisting>
+    </example>
+
+    <example>
+      <title>PCI WLAN card</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
+ID_NET_NAME_MAC=wlx0024d7e31130
+ID_NET_NAME_PATH=wlp3s0</programlisting>
+    </example>
+
+    <example>
+      <title>PCI IB host adapter with 2 ports</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/net/ibp21s0f0
+ID_NET_NAME_PATH=ibp21s0f0
+
+# /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.1/net/ibp21s0f1
+ID_NET_NAME_PATH=ibp21s0f1</programlisting>
+    </example>
+
+    <example>
+      <title>USB built-in 3G modem</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
+ID_NET_NAME_MAC=wwx028037ec0200
+ID_NET_NAME_PATH=wwp0s29u1u4i6</programlisting>
+    </example>
+
+    <example>
+      <title>USB Android phone</title>
+
+      <programlisting># /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
+ID_NET_NAME_MAC=enxd626b3450fb5
+ID_NET_NAME_PATH=enp0s29u1u2</programlisting>
+    </example>
+
+    <example>
+      <title>s390 grouped CCW interface</title>
+
+      <programlisting># /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
+ID_NET_NAME_MAC=enx026d3c00000a
+ID_NET_NAME_PATH=encf5f0</programlisting>
+    </example>
+  </refsect1>
+
+  <refsect1>
+    <title>See Also</title>
+    <para>
+      <citerefentry><refentrytitle>udev</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>udevadm</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <ulink url="https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames">the
+      original page describing stable interface names</ulink>
+    </para>
+  </refsect1>
+
+</refentry>
index 416874fbaff84a32a5826dc0858a0b6697c8f950..c746ed31f82b25e5df2b507f81475657bf0e8ae0 100644 (file)
           <row><entry><varname>ipvlan</varname></entry>
           <entry>An ipvlan device is a stacked device which receives packets from its underlying device based on IP address filtering.</entry></row>
 
+          <row><entry><varname>ipvtap</varname></entry>
+          <entry>An ipvtap device is a stacked device which receives packets from its underlying device based on IP address filtering and can be accessed using the tap user space interface.</entry></row>
+
           <row><entry><varname>macvlan</varname></entry>
           <entry>A macvlan device is a stacked device which receives packets from its underlying device based on MAC address filtering.</entry></row>
 
 
   </refsect1>
 
+  <refsect1>
+    <title>[IPVTAP] Section Options</title>
+
+    <para>The <literal>[IPVTAP]</literal> section only applies for
+    netdevs of kind <literal>ipvtap</literal> and accepts the
+    same key as <literal>[IPVLAN]</literal>.</para>
+
+  </refsect1>
+
   <refsect1>
     <title>[VXLAN] Section Options</title>
     <para>The <literal>[VXLAN]</literal> section only applies for
       <varlistentry>
         <term><varname>TTL=</varname></term>
         <listitem>
-          <para>A fixed Time To Live N on Virtual eXtensible Local
-          Area Network packets. N is a number in the range 1–255. 0
-          is a special value meaning that packets inherit the TTL
-          value.</para>
+          <para>A fixed Time To Live N on Virtual eXtensible Local Area Network packets.
+          Takes <literal>inherit</literal> or a number in the range 0–255. 0 is a special
+          value meaning inherit the inner protocol's TTL value. <literal>inherit</literal>
+          means that it will inherit the outer protocol's TTL value.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
       <varlistentry>
         <term><varname>Id=</varname></term>
         <listitem>
-          <para>Specifies the Virtual Network Identifier (VNI) to use. Ranges [0-16777215].</para>
+          <para>Specifies the Virtual Network Identifier (VNI) to use. Ranges [0-16777215]. This field is mandatory.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
       <varlistentry>
         <term><varname>TTL=</varname></term>
         <listitem>
-          <para>Specifies the TTL value to use in outgoing packets. Ranges [1-255].</para>
+          <para>Accepts the same key in <literal>[VXLAN]</literal> section except when unset or
+          set to 0, the kernel's default will be used meaning that packets TTL will be set from
+          <filename>/proc/sys/net/ipv4/ip_default_ttl</filename>.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <listitem>
           <para>Specifies the flow label to use in outgoing packets.</para>
         </listitem>
-      </varlistentry>
+    </varlistentry>
+    <varlistentry>
+      <term><varname>IPDoNotFragment=</varname></term>
+        <listitem>
+          <para>Accepts the same key in <literal>[VXLAN]</literal> section.</para>
+        </listitem>
+    </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
           for delivery to the real destination. This option is mandatory.</para>
         </listitem>
         </varlistentry>
+      <varlistentry>
+        <term><varname>PeerPort=</varname></term>
+        <listitem>
+          <para>Specifies the peer port number. Defaults to unset. Note that when peer port is set <literal>Peer=</literal> address is mandotory.</para>
+        </listitem>
+        </varlistentry>
       <varlistentry>
         <term><varname>Protocol=</varname></term>
         <listitem>
           <varname>Encapsulation=GenericUDPEncapsulation</varname>, this must not be specified.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>Peer=</varname></term>
+        <listitem>
+          <para>Configures peer IP address. Note that when peer address is set <literal>PeerPort=</literal> is mandotory.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>Local=</varname></term>
+        <listitem>
+          <para>Configures local IP address.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
index f24bf401595b5c5276a287db79679f416a88bfdc..695bcaa0a47020475e8056457cff8d6891e7cb25 100644 (file)
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>DefaultRouteOnDevice=</varname></term>
+          <listitem>
+            <para>Takes a boolean. If set to true, sets up the default route bound to the interface.
+            Defaults to false. This is useful when creating routes on point-to-point interfaces.
+            This is equivalent to e.g. the following.
+            <programlisting>ip route add default dev veth99</programlisting></para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>IPv6Token=</varname></term>
           <listitem>
             </para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>FastOpenNoCookie=</varname></term>
+          <listitem>
+            <para>Takes a boolean. When true enables TCP fastopen without a cookie on a per-route basis.
+            When unset, the kernel's default will be used.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>TTLPropagate=</varname></term>
+          <listitem>
+            <para>Takes a boolean. When true enables TTL propagation at Label Switched Path (LSP) egress.
+            When unset, the kernel's default will be used.
+            </para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
         <term><varname>MTUBytes=</varname></term>
         <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>SendRelease=</varname></term>
+          <listitem>
+            <para>When true, the DHCPv4 client sends a DHCP release packet when it stops.
+            Defaults to false.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>RapidCommit=</varname></term>
           <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>BlackList=</varname></term>
+          <listitem>
+            <para>A whitespace-separated list of IPv4 addresses. DHCP offers from servers in the list are rejected.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect1>
 
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>BlackList=</varname></term>
+          <listitem>
+            <para>A whitespace-separated list of IPv6 prefixes. IPv6 prefixes supplied via router advertisements in the list are ignored.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
   </refsect1>
 
             When unset, the kernel's default will be used.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>ProxyARP=</varname></term>
+          <listitem>
+            <para>Takes a boolean. Configures whether proxy ARP to be enabled on this port.
+            When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>ProxyARPWiFi=</varname></term>
+          <listitem>
+            <para>Takes a boolean. Configures whether proxy ARP to be enabled on this port
+            which meets extended requirements by IEEE 802.11 and Hotspot 2.0 specifications.
+            When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><varname>MulticastRouter=</varname></term>
+          <listitem>
+            <para>Configures this port for having multicast routers attached. A port with a multicast
+            router will receive all multicast traffic. Takes one of <literal>no</literal>
+            to disable multicast routers on this port, <literal>query</literal> to let the system detect
+            the presence of routers, <literal>permanent</literal> to permanently enable multicast traffic
+            forwarding on this port, or <literal>temporary</literal> to enable multicast routers temporarily
+            on this port, not depending on incoming queries. When unset, the kernel's default will be used.</para>
+          </listitem>
+        </varlistentry>
         <varlistentry>
           <term><varname>Cost=</varname></term>
           <listitem>
             Defaults to unset.</para>
           </listitem>
         </varlistentry>
+        <varlistentry>
+          <term><varname>AssociatedWith=</varname></term>
+          <listitem>
+            <para>Specifies where the address is associated with. Takes one of <literal>use</literal>,
+            <literal>self</literal>, <literal>master</literal> or <literal>router</literal>.
+            <literal>use</literal> means the address is in use. User space can use this option to
+            indicate to the kernel that the fdb entry is in use. <literal>self</literal> means
+            the address is associated with the port drivers fdb. Usually hardware. <literal>master</literal>
+            means the address is associated with master devices fdb. <literal>router</literal> means
+            the destination address is associated with a router. Note that it's valid if the referenced
+            device is a VXLAN type device and has route shortcircuit enabled. Defaults to <literal>self</literal>.</para>
+          </listitem>
+        </varlistentry>
       </variablelist>
   </refsect1>
 
index 4b283880c3d31901d7a62f66a35ceb47cbc3a496..3079db1a6ba6177e12e031e2c05b3b5f2611fd1c 100644 (file)
         or runtime environment doesn't require their functionality. Use the various
         <varname>AssertArchitecture=</varname>, <varname>AssertVirtualization=</varname>, â€¦ options for a similar
         mechanism that causes the job to fail (instead of being skipped) and results in logging about the failed check
-        (instead of being silently processed). For details about assertion conditions see below.</para>
+        (instead of being silently processed). For details about assertion conditions see below. Units with failed
+        conditions are considered to be in a clean state and will be garbage collected if they are not referenced.
+        This means, that when queried, the condition failure may or may not show up in the state of the unit.</para>
 
         <para><varname>ConditionArchitecture=</varname> may be used to
         check whether the system is running on a specific
         "Forward" and "reverse" unit properties
       </title>
 
-      <tgroup cols='2'>
+      <tgroup cols='4'>
         <colspec colname='forward' />
         <colspec colname='reverse' />
-        <colspec colname='notes' />
+        <colspec colname='fuse' />
+        <colspec colname='ruse' />
         <thead>
           <row>
             <entry>"Forward" property</entry>
             <entry>"Reverse" property</entry>
-            <entry>Where used</entry>
+            <entry namest='fuse' nameend='ruse' valign='middle'>Where used</entry>
           </row>
         </thead>
         <tbody>
           <row>
             <entry><varname>Before=</varname></entry>
             <entry><varname>After=</varname></entry>
-            <entry morerows='1' valign='middle'>Both are unit file options</entry>
+            <entry morerows='1' namest='fuse' nameend='ruse' valign='middle'>[Unit] section</entry>
           </row>
           <row>
             <entry><varname>After=</varname></entry>
           <row>
             <entry><varname>Requires=</varname></entry>
             <entry><varname>RequiredBy=</varname></entry>
-            <entry>A unit file option; an option in the [Install] section</entry>
+            <entry>[Unit] section</entry>
+            <entry>[Install] section</entry>
           </row>
           <row>
             <entry><varname>Wants=</varname></entry>
             <entry><varname>WantedBy=</varname></entry>
-            <entry>A unit file option; an option in the [Install] section</entry>
+            <entry>[Unit] section</entry>
+            <entry>[Install] section</entry>
           </row>
           <row>
             <entry><varname>PartOf=</varname></entry>
             <entry><varname>ConsistsOf=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>BindsTo=</varname></entry>
             <entry><varname>BoundBy=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>Requisite=</varname></entry>
             <entry><varname>RequisiteOf=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>Triggers=</varname></entry>
             <entry><varname>TriggeredBy=</varname></entry>
-            <entry>Automatic properties, see notes below</entry>
+            <entry namest='fuse' nameend='ruse' valign='middle'>Automatic properties, see notes below</entry>
           </row>
           <row>
             <entry><varname>Conflicts=</varname></entry>
             <entry><varname>ConflictedBy=</varname></entry>
-            <entry>A unit file option; an automatic property</entry>
+            <entry>[Unit] section</entry>
+            <entry>an automatic property</entry>
           </row>
           <row>
             <entry><varname>PropagatesReloadTo=</varname></entry>
             <entry><varname>ReloadPropagatedFrom=</varname></entry>
-            <entry morerows='1' valign='middle'>Both are unit file options</entry>
+            <entry morerows='1' namest='fuse' nameend='ruse' valign='middle'>[Unit] section</entry>
           </row>
           <row>
             <entry><varname>ReloadPropagatedFrom=</varname></entry>
index 35f8992345aa75939c2b4e3839e0d29adc21b378..c7c0c3ffd06f5d14fdee7f8b341c504df4f9f519 100644 (file)
@@ -304,7 +304,14 @@ else
 endif
 
 if want_libfuzzer
-        fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer')
+        fuzzing_engine = meson.get_compiler('cpp').find_library('Fuzzer', required : false)
+        if fuzzing_engine.found()
+                add_project_arguments('-fsanitize-coverage=trace-pc-guard,trace-cmp', language : 'c')
+        elif cc.has_argument('-fsanitize=fuzzer-no-link')
+                add_project_arguments('-fsanitize=fuzzer-no-link', language : 'c')
+        else
+                error('Looks like neither libFuzzer nor -fsanitize=fuzzer-no-link is supported')
+        endif
 elif want_ossfuzz
         fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
 elif want_fuzzbuzz
@@ -2826,9 +2833,16 @@ foreach tuple : fuzzers
         dependencies = tuple[2]
         defs = tuple.length() >= 4 ? tuple[3] : []
         incs = tuple.length() >= 5 ? tuple[4] : includes
+        link_args = []
 
-        if fuzzer_build
+        if want_ossfuzz or want_fuzzbuzz
                 dependencies += fuzzing_engine
+        elif want_libfuzzer
+                if fuzzing_engine.found()
+                        dependencies += fuzzing_engine
+                else
+                        link_args += ['-fsanitize=fuzzer']
+                endif
         else
                 sources += 'src/fuzz/fuzz-main.c'
         endif
@@ -2846,6 +2860,7 @@ foreach tuple : fuzzers
                 link_with : link_with,
                 dependencies : dependencies,
                 c_args : defs,
+                link_args: link_args,
                 install : false)
 endforeach
 endif
index 2b959635ebd3e5ded88b75b4e82276cbe894f6bf..1eafe5a6586275d3d2be6f7d778bef075a4a5e2c 100644 (file)
--- a/po/it.po
+++ b/po/it.po
@@ -7,7 +7,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: systemd\n"
-"Report-Msgid-Bugs-To: \n"
+"Report-Msgid-Bugs-To: https://github.com/systemd/systemd/issues\n"
 "POT-Creation-Date: 2019-05-05 17:02+0200\n"
 "PO-Revision-Date: 2019-05-05 17:13+0200\n"
 "Last-Translator: Daniele Medri <dmedri@gmail.com>\n"
@@ -102,11 +102,11 @@ msgstr ""
 
 #: src/hostname/org.freedesktop.hostname1.policy:51
 msgid "Get product UUID"
-msgstr "Ottieni UUID prodotto"
+msgstr "Ottieni UUID del prodotto"
 
 #: src/hostname/org.freedesktop.hostname1.policy:52
 msgid "Authentication is required to get product UUID."
-msgstr "Autenticazione richiesta per ottenere UUID prodotto."
+msgstr "Autenticazione richiesta per ottenere UUID del prodotto."
 
 #: src/import/org.freedesktop.import1.policy:22
 msgid "Import a VM or container image"
@@ -168,7 +168,7 @@ msgstr "Consenti alle applicazioni di ritardare lo spegnimento del sistema"
 #: src/login/org.freedesktop.login1.policy:34
 msgid "Authentication is required for an application to delay system shutdown."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per ritardare lo spegnimento "
+"Autenticazione richiesta ad un'applicazione per ritardare lo spegnimento "
 "del sistema."
 
 #: src/login/org.freedesktop.login1.policy:44
@@ -178,7 +178,7 @@ msgstr "Consenti alle applicazioni di inibire il sistema in pausa"
 #: src/login/org.freedesktop.login1.policy:45
 msgid "Authentication is required for an application to inhibit system sleep."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire il sistema in pausa."
+"Autenticazione richiesta ad un'applicazione per inibire il sistema in pausa."
 
 #: src/login/org.freedesktop.login1.policy:55
 msgid "Allow applications to delay system sleep"
@@ -187,7 +187,7 @@ msgstr "Consenti alle applicazioni di ritardare il sistema in pausa"
 #: src/login/org.freedesktop.login1.policy:56
 msgid "Authentication is required for an application to delay system sleep."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per ritardare il sistema in "
+"Autenticazione richiesta ad un'applicazione per ritardare il sistema in "
 "pausa."
 
 #: src/login/org.freedesktop.login1.policy:65
@@ -200,13 +200,13 @@ msgid ""
 "Authentication is required for an application to inhibit automatic system "
 "suspend."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la sospensione "
+"Autenticazione richiesta ad un'applicazione per inibire la sospensione "
 "automatica del sistema."
 
 #: src/login/org.freedesktop.login1.policy:75
 msgid "Allow applications to inhibit system handling of the power key"
 msgstr ""
-"Consenti alle applicazioni di inibire la gestione di sistema del tasto di "
+"Consenti alle applicazioni di inibire la gestione di sistema del tasto"
 "accensione"
 
 #: src/login/org.freedesktop.login1.policy:76
@@ -215,7 +215,7 @@ msgid ""
 "the power key."
 msgstr ""
 "Autenticazione richiesta per un'applicazione per inibire la gestione di "
-"sistema del tasto di accensione."
+"sistema del tasto accensione."
 
 #: src/login/org.freedesktop.login1.policy:86
 msgid "Allow applications to inhibit system handling of the suspend key"
@@ -228,7 +228,7 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the suspend key."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la gestione di "
+"Autenticazione richiesta ad un'applicazione per inibire la gestione di "
 "sistema del tasto di sospensione."
 
 #: src/login/org.freedesktop.login1.policy:97
@@ -242,7 +242,7 @@ msgid ""
 "Authentication is required for an application to inhibit system handling of "
 "the hibernate key."
 msgstr ""
-"Autenticazione richiesta per un'applicazione per inibire la gestione di "
+"Autenticazione richiesta ad un'applicazione per inibire la gestione di "
 "sistema del tasto di ibernazione."
 
 #: src/login/org.freedesktop.login1.policy:107
@@ -534,11 +534,11 @@ msgstr "Autenticazione richiesta per configurare un messaggio per gli utenti"
 
 #: src/machine/org.freedesktop.machine1.policy:22
 msgid "Log into a local container"
-msgstr "Accedi in un container locale"
+msgstr "Accedi ad un container locale"
 
 #: src/machine/org.freedesktop.machine1.policy:23
 msgid "Authentication is required to log into a local container."
-msgstr "Autenticazione richiesta per accedere in un container locale."
+msgstr "Autenticazione richiesta per accedere ad un container locale."
 
 #: src/machine/org.freedesktop.machine1.policy:32
 msgid "Log into the local host"
@@ -546,7 +546,7 @@ msgstr "Accedi in un host locale"
 
 #: src/machine/org.freedesktop.machine1.policy:33
 msgid "Authentication is required to log into the local host."
-msgstr "Autenticazione richiesta per accedere in un host locale."
+msgstr "Autenticazione richiesta per accedere ad un host locale."
 
 #: src/machine/org.freedesktop.machine1.policy:42
 msgid "Acquire a shell in a local container"
@@ -650,7 +650,7 @@ msgstr "Annulla la registrazione di un servizio DNS-SD"
 #: src/resolve/org.freedesktop.resolve1.policy:34
 msgid "Authentication is required to unregister a DNS-SD service"
 msgstr ""
-"Autenticazione richiesta per annullare la registrare di un servizio DNS-SD"
+"Autenticazione richiesta per annullare la registrazione di un servizio DNS-SD"
 
 #: src/timedate/org.freedesktop.timedate1.policy:22
 msgid "Set system time"
@@ -692,7 +692,7 @@ msgid ""
 "shall be enabled."
 msgstr ""
 "Autenticazione richiesta per verificare se la sincronizzazione dell'orario "
-"in rete possa essere attivata."
+"in rete deve essere attivata."
 
 #: src/core/dbus-unit.c:317
 msgid "Authentication is required to start '$(unit)'."
index bc320962c131c7d5e9651614aaf22de045a65415..1951dcbbada6a8e9fe6bdf33025ac99e8b8fb4ea 100755 (executable)
@@ -5,6 +5,7 @@ set -eux
 # default to Debian testing
 DISTRO=${DISTRO:-debian}
 RELEASE=${RELEASE:-buster}
+BRANCH=${BRANCH:-experimental}
 ARCH=${ARCH:-amd64}
 CONTAINER=${RELEASE}-${ARCH}
 MAX_CACHE_AGE=604800  # one week
@@ -66,7 +67,7 @@ for phase in "${PHASES[@]}"; do
         ;;
         RUN)
             # add current debian/ packaging
-            git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git master
+            git fetch --depth=1 https://salsa.debian.org/systemd-team/systemd.git $BRANCH
             git checkout FETCH_HEAD debian
 
             # craft changelog
index 09d26da0db46bbf5bea81e6e9add16abcc4bb998..e6bbb179dea6cdf3663562d6294c043f9be83e20 100644 (file)
@@ -1873,8 +1873,8 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --require             Show only requirement in the graph\n"
                "     --from-pattern=GLOB   Show only origins in the graph\n"
                "     --to-pattern=GLOB     Show only destinations in the graph\n"
-               "     --fuzz=SECONDS        Also print also services which finished SECONDS\n"
-               "                           earlier than the latest in the branch\n"
+               "     --fuzz=SECONDS        Also print services which finished SECONDS earlier\n"
+               "                           than the latest in the branch\n"
                "     --man[=BOOL]          Do [not] check for existence of man pages\n"
                "     --generators[=BOOL]   Do [not] run unit generators (requires privileges)\n"
                "     --iterations=N        Show the specified number of iterations\n"
index b9651205e60818661ebf97af4e8cfc38f0e9c8bb..c153bc4448da61ccae1f5beabfaa7dd1d29e7b0f 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <sys/inotify.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
 
index 1d5c6412b5ba50bcd587a3e2dba92acb6b84abb9..c1fab51b5e43db651d29dce01077d269bb98d862 100644 (file)
@@ -738,3 +738,15 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
 }
 
 DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
+
+static void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
+        assert(addr);
+
+        siphash24_compress(addr, sizeof(*addr), state);
+}
+
+static int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
+        return memcmp(a, b, sizeof(*a));
+}
+
+DEFINE_HASH_OPS(in6_addr_hash_ops, struct in6_addr, in6_addr_hash_func, in6_addr_compare_func);
index a6a685b9188b5084e1b699a0afbb535cf77a1c41..2ca7f4b32fc88b5d8a9ecd2674661839821f4015 100644 (file)
@@ -72,3 +72,4 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
 #define IN_ADDR_NULL ((union in_addr_union) { .in6 = {} })
 
 extern const struct hash_ops in_addr_data_hash_ops;
+extern const struct hash_ops in6_addr_hash_ops;
index f849f34951281300e64c49974cc54c350e9e805c..2bb70fdaadb812a6ea231ab8b9428f7708722983 100644 (file)
@@ -1,3 +1,6 @@
-The files in this directory are copied from kernel-5.0, and the following modifications are applied:
+The files in this directory are copied from current kernel master
+(b06ed1e7a2fa9b636f368a9e97c3c8877623f8b2) or WireGuard master
+(8416093498ac2c754536dad4757c5d86c9ba8809), and the following
+modifications are applied:
 - btrfs.h: drop '__user' attributes
 - if.h: drop '#include <linux/compiler.h>' and '__user' attributes
index f477008fef0876827c0fa35670bf6e2cc49b527f..b960b45d674290fdb32a2ce6ff0a46afcad973d0 100644 (file)
@@ -135,7 +135,7 @@ struct btrfs_scrub_progress {
        __u64 tree_bytes_scrubbed;      /* # of tree bytes scrubbed */
        __u64 read_errors;              /* # of read errors encountered (EIO) */
        __u64 csum_errors;              /* # of failed csum checks */
-       __u64 verify_errors;            /* # of occurrences, where the metadata
+       __u64 verify_errors;            /* # of occurences, where the metadata
                                         * of a tree block did not match the
                                         * expected values, like generation or
                                         * logical */
@@ -155,7 +155,7 @@ struct btrfs_scrub_progress {
        __u64 last_physical;            /* last physical address scrubbed. In
                                         * case a scrub was aborted, this can
                                         * be used to restart the scrub */
-       __u64 unverified_errors;        /* # of occurrences where a read for a
+       __u64 unverified_errors;        /* # of occurences where a read for a
                                         * full (64k) bio failed, but the re-
                                         * check succeeded for each 4k piece.
                                         * Intermittent error. */
@@ -837,6 +837,8 @@ enum btrfs_err_code {
                                   struct btrfs_ioctl_vol_args)
 #define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \
                                   struct btrfs_ioctl_vol_args)
+#define BTRFS_IOC_FORGET_DEV _IOW(BTRFS_IOCTL_MAGIC, 5, \
+                                  struct btrfs_ioctl_vol_args)
 /* trans start and trans end are dangerous, and only for
  * use by applications that know how to avoid the
  * resulting deadlocks
index 0d933ba3a12ef3206b764785fb18af3ce7cfb038..421239b98db2c79e9a9e3fe57c5013716af43603 100644 (file)
@@ -54,7 +54,7 @@
 /* for storing balance parameters in the root tree */
 #define BTRFS_BALANCE_OBJECTID -4ULL
 
-/* orphan objectid for tracking unlinked/truncated files */
+/* orhpan objectid for tracking unlinked/truncated files */
 #define BTRFS_ORPHAN_OBJECTID -5ULL
 
 /* does write ahead logging to speed up fsyncs */
 #define BTRFS_PERSISTENT_ITEM_KEY      249
 
 /*
- * Persistently stores the device replace state in the device tree.
+ * Persistantly stores the device replace state in the device tree.
  * The key is built like this: (0, BTRFS_DEV_REPLACE_KEY, 0).
  */
 #define BTRFS_DEV_REPLACE_KEY  250
  *
  * Used by:
  * struct btrfs_dir_item.type
+ *
+ * Values 0..7 must match common file type values in fs_types.h.
  */
 #define BTRFS_FT_UNKNOWN       0
 #define BTRFS_FT_REG_FILE      1
index f2ea833a2812561d7b10517a39e695589e8b236b..87c2c9f0880304e20202350ea164b9293e085d50 100644 (file)
@@ -16,6 +16,12 @@ enum {
        FOU_ATTR_IPPROTO,                       /* u8 */
        FOU_ATTR_TYPE,                          /* u8 */
        FOU_ATTR_REMCSUM_NOPARTIAL,             /* flag */
+       FOU_ATTR_LOCAL_V4,                      /* u32 */
+       FOU_ATTR_LOCAL_V6,                      /* in6_addr */
+       FOU_ATTR_PEER_V4,                       /* u32 */
+       FOU_ATTR_PEER_V6,                       /* in6_addr */
+       FOU_ATTR_PEER_PORT,                     /* u16 */
+       FOU_ATTR_IFINDEX,                       /* s32 */
 
        __FOU_ATTR_MAX,
 };
index cbabdde8f9da5163391c53d59c4ef67c16f42727..4c6f030afc14e71048aa73da2b6f99c9388d6d47 100644 (file)
@@ -179,7 +179,7 @@ enum {
 };
 
 /*
- *     Device mapping structure. I'd just gone off and designed a
+ *     Device mapping structure. I'd just gone off and designed a 
  *     beautiful scheme using only loadable modules with arguments
  *     for driver options and along come the PCMCIA people 8)
  *
@@ -193,7 +193,7 @@ enum {
 struct ifmap {
        unsigned long mem_start;
        unsigned long mem_end;
-       unsigned short base_addr;
+       unsigned short base_addr; 
        unsigned char irq;
        unsigned char dma;
        unsigned char port;
@@ -233,7 +233,7 @@ struct ifreq {
        {
                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
        } ifr_ifrn;
-
+       
        union {
                struct  sockaddr ifru_addr;
                struct  sockaddr ifru_dstaddr;
index 61a1bf6e865e8b41aa1f5bd8ce188f513f58e143..790585f0e61b5b252a03bd558694dc4c8921246b 100644 (file)
@@ -117,6 +117,30 @@ struct ad_info {
        __u8 partner_system[ETH_ALEN];
 };
 
+/* Embedded inside LINK_XSTATS_TYPE_BOND */
+enum {
+       BOND_XSTATS_UNSPEC,
+       BOND_XSTATS_3AD,
+       __BOND_XSTATS_MAX
+};
+#define BOND_XSTATS_MAX (__BOND_XSTATS_MAX - 1)
+
+/* Embedded inside BOND_XSTATS_3AD */
+enum {
+       BOND_3AD_STAT_LACPDU_RX,
+       BOND_3AD_STAT_LACPDU_TX,
+       BOND_3AD_STAT_LACPDU_UNKNOWN_RX,
+       BOND_3AD_STAT_LACPDU_ILLEGAL_RX,
+       BOND_3AD_STAT_MARKER_RX,
+       BOND_3AD_STAT_MARKER_TX,
+       BOND_3AD_STAT_MARKER_RESP_RX,
+       BOND_3AD_STAT_MARKER_RESP_TX,
+       BOND_3AD_STAT_MARKER_UNKNOWN_RX,
+       BOND_3AD_STAT_PAD,
+       __BOND_3AD_STAT_MAX
+};
+#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1)
+
 #endif /* _LINUX_IF_BONDING_H */
 
 /*
index 3a45b4ad71a3083a16085d69e2891e31dddcdaa8..3158ba672b72ba24b97a5e7f341389c629202c11 100644 (file)
 #define ETH_P_QINQ2    0x9200          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3    0x9300          /* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA     0xDADA          /* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_8021Q        0xDADB          /* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IFE      0xED3E          /* ForCES inter-FE LFB type */
 #define ETH_P_AF_IUCV   0xFBFB         /* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
index d6533828123a6728958d2127ab81c2b5fa30f07f..5b225ff63b483145878e977cf0a1be7d1fe53cd9 100644 (file)
@@ -925,6 +925,7 @@ enum {
 enum {
        LINK_XSTATS_TYPE_UNSPEC,
        LINK_XSTATS_TYPE_BRIDGE,
+       LINK_XSTATS_TYPE_BOND,
        __LINK_XSTATS_TYPE_MAX
 };
 #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
index 23a6753b37df3a0a241c2986aa932301bef02b1f..454ae31b93c7a4b4aeedddf7ceb5274377b39a58 100644 (file)
@@ -60,6 +60,7 @@
 #define TUNSETSTEERINGEBPF _IOR('T', 224, int)
 #define TUNSETFILTEREBPF _IOR('T', 225, int)
 #define TUNSETCARRIER _IOW('T', 226, int)
+#define TUNGETDEVNETNS _IO('T', 227)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001
index a55cb8b10165abcf8a07d8228b590bbc1d8a0c08..e7ad9d350a283d81e89696e1bc42438030accc90 100644 (file)
@@ -292,10 +292,11 @@ struct sockaddr_in {
 #define        IN_LOOPBACK(a)          ((((long int) (a)) & 0xff000000) == 0x7f000000)
 
 /* Defines for Multicast INADDR */
-#define INADDR_UNSPEC_GROUP    0xe0000000U     /* 224.0.0.0   */
-#define INADDR_ALLHOSTS_GROUP  0xe0000001U     /* 224.0.0.1   */
-#define INADDR_ALLRTRS_GROUP    0xe0000002U    /* 224.0.0.2 */
-#define INADDR_MAX_LOCAL_GROUP  0xe00000ffU    /* 224.0.0.255 */
+#define INADDR_UNSPEC_GROUP            0xe0000000U     /* 224.0.0.0   */
+#define INADDR_ALLHOSTS_GROUP          0xe0000001U     /* 224.0.0.1   */
+#define INADDR_ALLRTRS_GROUP           0xe0000002U     /* 224.0.0.2 */
+#define INADDR_ALLSNOOPERS_GROUP       0xe000006aU     /* 224.0.0.106 */
+#define INADDR_MAX_LOCAL_GROUP         0xe00000ffU     /* 224.0.0.255 */
 #endif
 
 /* <asm/byteorder.h> contains the htonl type stuff.. */
index 9fa75591c5662d5b84d08d35dbe595bc052062b5..9f2273a0835642b243a7c10903ac24b79ecb9f99 100644 (file)
@@ -178,13 +178,14 @@ struct in6_flowlabel_req {
 #define IPV6_JOIN_ANYCAST      27
 #define IPV6_LEAVE_ANYCAST     28
 #define IPV6_MULTICAST_ALL     29
+#define IPV6_ROUTER_ALERT_ISOLATE      30
 
 /* IPV6_MTU_DISCOVER values */
 #define IPV6_PMTUDISC_DONT             0
 #define IPV6_PMTUDISC_WANT             1
 #define IPV6_PMTUDISC_DO               2
 #define IPV6_PMTUDISC_PROBE            3
-/* same as IPV6_PMTUDISC_PROBE, provided for symmetry with IPv4
+/* same as IPV6_PMTUDISC_PROBE, provided for symetry with IPv4
  * also see comments on IP_PMTUDISC_INTERFACE
  */
 #define IPV6_PMTUDISC_INTERFACE                4
diff --git a/src/basic/linux/update.sh b/src/basic/linux/update.sh
new file mode 100755 (executable)
index 0000000..b232070
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+set -eu
+
+for i in *.h */*.h; do
+    if [[ $i == 'wireguard.h' ]]; then
+        curl https://raw.githubusercontent.com/WireGuard/WireGuard/master/src/uapi/$i -o $i
+    else
+        curl https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/$i -o $i
+    fi
+
+    sed -i -e 's/__user //g' -e '/^#include <linux\/compiler.h>/ d' $i
+done
index 3dc3534e1ab21556b2bc81918345ed93c3876ad5..052bce6645f396694cac5da55274d792c0547d1f 100644 (file)
@@ -44,7 +44,7 @@
 #include "terminal-util.h"
 #include "user-util.h"
 
-int get_process_state(pid_t pid) {
+static int get_process_state(pid_t pid) {
         const char *p;
         char state;
         int r;
index 7e1d65a7bf1b3c52c9b7c8d3e982d72be127308d..83ba93d0d74aa3b45aa8558ce14bfe85dd025118 100644 (file)
@@ -31,7 +31,6 @@
                 _r_;                                                    \
         })
 
-int get_process_state(pid_t pid);
 int get_process_comm(pid_t pid, char **name);
 int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line);
 int get_process_exe(pid_t pid, char **name);
index b8bbf2d418f1effecf7d4abcf1d644a120b679b6..3af6f271f0e38eba268378052ee965c5828778d4 100644 (file)
 
 int rdrand(unsigned long *ret) {
 
+        /* So, you are a "security researcher", and you wonder why we bother with using raw RDRAND here,
+         * instead of sticking to /dev/urandom or getrandom()?
+         *
+         * Here's why: early boot. On Linux, during early boot the random pool that backs /dev/urandom and
+         * getrandom() is generally not initialized yet. It is very common that initialization of the random
+         * pool takes a longer time (up to many minutes), in particular on embedded devices that have no
+         * explicit hardware random generator, as well as in virtualized environments such as major cloud
+         * installations that do not provide virtio-rng or a similar mechanism.
+         *
+         * In such an environment using getrandom() synchronously means we'd block the entire system boot-up
+         * until the pool is initialized, i.e. *very* long. Using getrandom() asynchronously (GRND_NONBLOCK)
+         * would mean acquiring randomness during early boot would simply fail. Using /dev/urandom would mean
+         * generating many kmsg log messages about our use of it before the random pool is properly
+         * initialized. Neither of these outcomes is desirable.
+         *
+         * Thus, for very specific purposes we use RDRAND instead of either of these three options. RDRAND
+         * provides us quickly and relatively reliably with random values, without having to delay boot,
+         * without triggering warning messages in kmsg.
+         *
+         * Note that we use RDRAND only under very specific circumstances, when the requirements on the
+         * quality of the returned entropy permit it. Specifically, here are some cases where we *do* use
+         * RDRAND:
+         *
+         *         â€¢ UUID generation: UUIDs are supposed to be universally unique but are not cryptographic
+         *           key material. The quality and trust level of RDRAND should hence be OK: UUIDs should be
+         *           generated in a way that is reliably unique, but they do not require ultimate trust into
+         *           the entropy generator. systemd generates a number of UUIDs during early boot, including
+         *           'invocation IDs' for every unit spawned that identify the specific invocation of the
+         *           service globally, and a number of others. Other alternatives for generating these UUIDs
+         *           have been considered, but don't really work: for example, hashing uuids from a local
+         *           system identifier combined with a counter falls flat because during early boot disk
+         *           storage is not yet available (think: initrd) and thus a system-specific ID cannot be
+         *           stored or retrieved yet.
+         *
+         *         â€¢ Hash table seed generation: systemd uses many hash tables internally. Hash tables are
+         *           generally assumed to have O(1) access complexity, but can deteriorate to prohibitive
+         *           O(n) access complexity if an attacker manages to trigger a large number of hash
+         *           collisions. Thus, systemd (as any software employing hash tables should) uses seeded
+         *           hash functions for its hash tables, with a seed generated randomly. The hash tables
+         *           systemd employs watch the fill level closely and reseed if necessary. This allows use of
+         *           a low quality RNG initially, as long as it improves should a hash table be under attack:
+         *           the attacker after all needs to to trigger many collisions to exploit it for the purpose
+         *           of DoS, but if doing so improves the seed the attack surface is reduced as the attack
+         *           takes place.
+         *
+         * Some cases where we do NOT use RDRAND are:
+         *
+         *         â€¢ Generation of cryptographic key material ðŸ”‘
+         *
+         *         â€¢ Generation of cryptographic salt values ðŸ§‚
+         *
+         * This function returns:
+         *
+         *         -EOPNOTSUPP â†’ RDRAND is not available on this system ðŸ˜”
+         *         -EAGAIN     â†’ The operation failed this time, but is likely to work if you try again a few
+         *                       times â™»
+         *         -EUCLEAN    â†’ We got some random value, but it looked strange, so we refused using it.
+         *                       This failure might or might not be temporary. ðŸ˜•
+         */
+
 #if defined(__i386__) || defined(__x86_64__)
         static int have_rdrand = -1;
+        unsigned long v;
         uint8_t success;
 
         if (have_rdrand < 0) {
@@ -59,12 +120,24 @@ int rdrand(unsigned long *ret) {
 
         asm volatile("rdrand %0;"
                      "setc %1"
-                     : "=r" (*ret),
+                     : "=r" (v),
                        "=qm" (success));
         msan_unpoison(&success, sizeof(success));
         if (!success)
                 return -EAGAIN;
 
+        /* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success
+         * via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be
+         * a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking
+         * for this special value (and also 0, just to be sure) and filtering it out. This is a work-around
+         * only however and something AMD really should fix properly. The Linux kernel should probably work
+         * around this issue by turning off RDRAND altogether on those CPUs. See:
+         * https://github.com/systemd/systemd/issues/11810 */
+        if (v == 0 || v == ULONG_MAX)
+                return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
+                                       "RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v);
+
+        *ret = v;
         return 0;
 #else
         return -EOPNOTSUPP;
@@ -77,10 +150,20 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
         bool got_some = false;
         int r;
 
-        /* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This
-         * call won't block, unless the RANDOM_BLOCK flag is set. If RANDOM_MAY_FAIL is set, an error is
-         * returned if the random pool is not initialized. Otherwise it will always return some data from the
-         * kernel, regardless of whether the random pool is fully initialized or not. */
+        /* Gathers some high-quality randomness from the kernel (or potentially mid-quality randomness from
+         * the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't block, unless the RANDOM_BLOCK
+         * flag is set. If RANDOM_MAY_FAIL is set, an error is returned if the random pool is not
+         * initialized. Otherwise it will always return some data from the kernel, regardless of whether the
+         * random pool is fully initialized or not. If RANDOM_EXTEND_WITH_PSEUDO is set, and some but not
+         * enough better quality randomness could be acquired, the rest is filled up with low quality
+         * randomness.
+         *
+         * Of course, when creating cryptographic key material you really shouldn't use RANDOM_ALLOW_DRDRAND
+         * or even RANDOM_EXTEND_WITH_PSEUDO.
+         *
+         * When generating UUIDs it's fine to use RANDOM_ALLOW_RDRAND but not OK to use
+         * RANDOM_EXTEND_WITH_PSEUDO. In fact RANDOM_EXTEND_WITH_PSEUDO is only really fine when invoked via
+         * an "all bets are off" wrapper, such as random_bytes(), see below. */
 
         if (n == 0)
                 return 0;
@@ -242,6 +325,11 @@ void initialize_srand(void) {
 void pseudo_random_bytes(void *p, size_t n) {
         uint8_t *q;
 
+        /* This returns pseudo-random data using libc's rand() function. You probably never want to call this
+         * directly, because why would you use this if you can get better stuff cheaply? Use random_bytes()
+         * instead, see below: it will fall back to this function if there's nothing better to get, but only
+         * then. */
+
         initialize_srand();
 
         for (q = p; q < (uint8_t*) p + n; q += RAND_STEP) {
@@ -263,6 +351,38 @@ void pseudo_random_bytes(void *p, size_t n) {
 
 void random_bytes(void *p, size_t n) {
 
+        /* This returns high quality randomness if we can get it cheaply. If we can't because for some reason
+         * it is not available we'll try some crappy fallbacks.
+         *
+         * What this function will do:
+         *
+         *         â€¢ This function will preferably use the CPU's RDRAND operation, if it is available, in
+         *           order to return "mid-quality" random values cheaply.
+         *
+         *         â€¢ Use getrandom() with GRND_NONBLOCK, to return high-quality random values if they are
+         *           cheaply available.
+         *
+         *         â€¢ This function will return pseudo-random data, generated via libc rand() if nothing
+         *           better is available.
+         *
+         *         â€¢ This function will work fine in early boot
+         *
+         *         â€¢ This function will always succeed
+         *
+         * What this function won't do:
+         *
+         *         â€¢ This function will never fail: it will give you randomness no matter what. It might not
+         *           be high quality, but it will return some, possibly generated via libc's rand() call.
+         *
+         *         â€¢ This function will never block: if the only way to get good randomness is a blocking,
+         *           synchronous getrandom() we'll instead provide you with pseudo-random data.
+         *
+         * This function is hence great for things like seeding hash tables, generating random numeric UNIX
+         * user IDs (that are checked for collisions before use) and such.
+         *
+         * This function is hence not useful for generating UUIDs or cryptographic key material.
+         */
+
         if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
                 return;
 
index 6920fd99ba5d4ac27a67eae8ebeb607777e42a38..36ec422f2c09103d458e7fc6d1f09fe5425b66f6 100644 (file)
@@ -9,6 +9,7 @@
 #include <netinet/in.h>
 #include <stdbool.h>
 #include <stddef.h>
+#include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
index cd878551f4982a054faa457c36c048703d20f1d9..71238ac9c43579079f9182be18f62f1e97c47513 100644 (file)
@@ -1249,12 +1249,36 @@ int vt_default_utf8(void) {
         return parse_boolean(b);
 }
 
+int vt_verify_kbmode(int fd) {
+        int curr_mode;
+
+        /*
+         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
+         * Otherwise we would (likely) interfere with X11's processing of the
+         * key events.
+         *
+         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
+         */
+
+        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
+                return -errno;
+
+        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
+}
+
 int vt_reset_keyboard(int fd) {
-        int kb;
+        int kb, r;
 
         /* If we can't read the default, then default to unicode. It's 2017 after all. */
         kb = vt_default_utf8() != 0 ? K_UNICODE : K_XLATE;
 
+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_debug_errno(r, "Keyboard is not in XLATE or UNICODE mode, not resetting: %m");
+                return 0;
+        } else if (r < 0)
+                return r;
+
         if (ioctl(fd, KDSKBMODE, kb) < 0)
                 return -errno;
 
index f3e785e7ba327ad25e8a2c7266cb27c6362fd3b0..ae9cda403b84f3afdefb51d6b93ee220cb116c4d 100644 (file)
 #include "time-util.h"
 
 /* Regular colors */
-#define ANSI_BLACK   "\x1B[0;30m"
 #define ANSI_RED     "\x1B[0;31m"
 #define ANSI_GREEN   "\x1B[0;32m"
 #define ANSI_YELLOW  "\x1B[0;33m"
 #define ANSI_BLUE    "\x1B[0;34m"
 #define ANSI_MAGENTA "\x1B[0;35m"
-#define ANSI_CYAN    "\x1B[0;36m"
-#define ANSI_WHITE   "\x1B[0;37m"
-#define ANSI_GREY    "\x1B[0;2;37m"
+#define ANSI_GREY    "\x1B[0;38;5;245m"
 
 /* Bold/highlighted */
-#define ANSI_HIGHLIGHT_BLACK   "\x1B[0;1;30m"
 #define ANSI_HIGHLIGHT_RED     "\x1B[0;1;31m"
 #define ANSI_HIGHLIGHT_GREEN   "\x1B[0;1;32m"
 #define ANSI_HIGHLIGHT_YELLOW  "\x1B[0;1;33m"
 #define ANSI_HIGHLIGHT_BLUE    "\x1B[0;1;34m"
 #define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
-#define ANSI_HIGHLIGHT_CYAN    "\x1B[0;1;36m"
-#define ANSI_HIGHLIGHT_WHITE   "\x1B[0;1;37m"
+#define ANSI_HIGHLIGHT_GREY    "\x1B[0;1;38;5;245m"
 
 /* Underlined */
-#define ANSI_HIGHLIGHT_BLACK_UNDERLINE   "\x1B[0;1;4;30m"
 #define ANSI_HIGHLIGHT_RED_UNDERLINE     "\x1B[0;1;4;31m"
 #define ANSI_HIGHLIGHT_GREEN_UNDERLINE   "\x1B[0;1;4;32m"
 #define ANSI_HIGHLIGHT_YELLOW_UNDERLINE  "\x1B[0;1;4;33m"
 #define ANSI_HIGHLIGHT_BLUE_UNDERLINE    "\x1B[0;1;4;34m"
 #define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
-#define ANSI_HIGHLIGHT_CYAN_UNDERLINE    "\x1B[0;1;4;36m"
-#define ANSI_HIGHLIGHT_WHITE_UNDERLINE   "\x1B[0;1;4;37m"
+#define ANSI_HIGHLIGHT_GREY_UNDERLINE    "\x1B[0;1;4;38;5;245m"
 
 /* Other ANSI codes */
 #define ANSI_UNDERLINE "\x1B[0;4m"
@@ -127,21 +120,29 @@ bool dev_console_colors_enabled(void);
                         colors_enabled() ? ANSI_##REPLACEMENT : "";     \
         }
 
-DEFINE_ANSI_FUNC(highlight,                  HIGHLIGHT);
-DEFINE_ANSI_FUNC(highlight_red,              HIGHLIGHT_RED);
-DEFINE_ANSI_FUNC(highlight_green,            HIGHLIGHT_GREEN);
-DEFINE_ANSI_FUNC(highlight_yellow,           HIGHLIGHT_YELLOW);
-DEFINE_ANSI_FUNC(highlight_blue,             HIGHLIGHT_BLUE);
-DEFINE_ANSI_FUNC(highlight_magenta,          HIGHLIGHT_MAGENTA);
-DEFINE_ANSI_FUNC(normal,                     NORMAL);
-DEFINE_ANSI_FUNC(grey,                       GREY);
-
-DEFINE_ANSI_FUNC_UNDERLINE(underline,                  UNDERLINE, NORMAL);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline,        HIGHLIGHT_UNDERLINE, HIGHLIGHT);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline,    HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline,  HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline, HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW);
-DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline,   HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(normal,            NORMAL);
+DEFINE_ANSI_FUNC(highlight,         HIGHLIGHT);
+DEFINE_ANSI_FUNC(red,               RED);
+DEFINE_ANSI_FUNC(green,             GREEN);
+DEFINE_ANSI_FUNC(yellow,            YELLOW);
+DEFINE_ANSI_FUNC(blue,              BLUE);
+DEFINE_ANSI_FUNC(magenta,           MAGENTA);
+DEFINE_ANSI_FUNC(grey,              GREY);
+DEFINE_ANSI_FUNC(highlight_red,     HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC(highlight_green,   HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC(highlight_yellow,  HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC(highlight_blue,    HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
+DEFINE_ANSI_FUNC(highlight_grey,    HIGHLIGHT_GREY);
+
+DEFINE_ANSI_FUNC_UNDERLINE(underline,                   UNDERLINE, NORMAL);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline,         HIGHLIGHT_UNDERLINE, HIGHLIGHT);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline,     HIGHLIGHT_RED_UNDERLINE, HIGHLIGHT_RED);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline,   HIGHLIGHT_GREEN_UNDERLINE, HIGHLIGHT_GREEN);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_yellow_underline,  HIGHLIGHT_YELLOW_UNDERLINE, HIGHLIGHT_YELLOW);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline,    HIGHLIGHT_BLUE_UNDERLINE, HIGHLIGHT_BLUE);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA_UNDERLINE, HIGHLIGHT_MAGENTA);
+DEFINE_ANSI_FUNC_UNDERLINE(highlight_grey_underline,    HIGHLIGHT_GREY_UNDERLINE, HIGHLIGHT_GREY);
 
 int get_ctty_devnr(pid_t pid, dev_t *d);
 int get_ctty(pid_t, dev_t *_devnr, char **r);
@@ -156,6 +157,7 @@ int openpt_in_namespace(pid_t pid, int flags);
 int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
 
 int vt_default_utf8(void);
+int vt_verify_kbmode(int fd);
 int vt_reset_keyboard(int fd);
 int vt_restore(int fd);
 int vt_release(int fd, bool restore_vt);
index 9df181a10c957860d1b5dbc8b771f168455b61e2..55924adf069cdd0daf10c3d38b62d4e61a9a8e0f 100644 (file)
@@ -326,7 +326,7 @@ static int boot_entry_file_check(const char *root, const char *p) {
 static void boot_entry_file_list(const char *field, const char *root, const char *p, int *ret_status) {
         int status = boot_entry_file_check(root, p);
 
-        printf("%13s%s", strempty(field), field ? ":" : " ");
+        printf("%13s%s ", strempty(field), field ? ":" : " ");
         if (status < 0) {
                 errno = -status;
                 printf("%s%s%s (%m)\n", ansi_highlight_red(), p, ansi_normal());
@@ -997,7 +997,7 @@ static int help(int argc, char *argv[], void *userdata) {
                "     --esp-path=PATH   Path to the EFI System Partition (ESP)\n"
                "     --boot-path=PATH  Path to the $BOOT partition\n"
                "  -p --print-esp-path  Print path to the EFI System Partition\n"
-               "     --print-boot-path Print path to the $BOOT partition\n"
+               "  -x --print-boot-path Print path to the $BOOT partition\n"
                "     --no-variables    Don't touch EFI variables\n"
                "     --no-pager        Do not pipe output into a pager\n"
                "\nBoot Loader Commands:\n"
@@ -1020,7 +1020,6 @@ static int parse_argv(int argc, char *argv[]) {
         enum {
                 ARG_ESP_PATH = 0x100,
                 ARG_BOOT_PATH,
-                ARG_PRINT_BOOT_PATH,
                 ARG_VERSION,
                 ARG_NO_VARIABLES,
                 ARG_NO_PAGER,
@@ -1034,7 +1033,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "boot-path",       required_argument, NULL, ARG_BOOT_PATH       },
                 { "print-esp-path",  no_argument,       NULL, 'p'                 },
                 { "print-path",      no_argument,       NULL, 'p'                 }, /* Compatibility alias */
-                { "print-boot-path", no_argument,       NULL, ARG_PRINT_BOOT_PATH },
+                { "print-boot-path", no_argument,       NULL, 'x'                 },
                 { "no-variables",    no_argument,       NULL, ARG_NO_VARIABLES    },
                 { "no-pager",        no_argument,       NULL, ARG_NO_PAGER        },
                 {}
@@ -1045,7 +1044,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "hp", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "hpx", options, NULL)) >= 0)
                 switch (c) {
 
                 case 'h':
@@ -1068,10 +1067,16 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case 'p':
+                        if (arg_print_dollar_boot_path)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
                         arg_print_esp_path = true;
                         break;
 
-                case ARG_PRINT_BOOT_PATH:
+                case 'x':
+                        if (arg_print_esp_path)
+                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+                                                       "--print-boot-path/-x cannot be combined with --print-esp-path/-p");
                         arg_print_dollar_boot_path = true;
                         break;
 
index b7848648bebfd430ed0c86c161937feff3200e1d..c11cb23aa9f2f0488c11ea95f1f63955d5c15ada 100644 (file)
@@ -2472,7 +2472,7 @@ static int manager_dispatch_sigchld(sd_event_source *source, void *userdata) {
         assert(source);
         assert(m);
 
-        /* First we call waitd() for a PID and do not reap the zombie. That way we can still access /proc/$PID for it
+        /* First we call waitid() for a PID and do not reap the zombie. That way we can still access /proc/$PID for it
          * while it is a zombie. */
 
         if (waitid(P_ALL, 0, &si, WEXITED|WNOHANG|WNOWAIT) < 0) {
index 86ab35d818d2c032cae4ff5da646d380d22bbc0f..f1df760a676cc69848e1313c2e793e956304ba45 100644 (file)
@@ -212,10 +212,6 @@ meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir))
 meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir))
 meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir))
 
-meson.add_install_script('sh', '-c',
-                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/multi-user.target.wants')))
-meson.add_install_script('sh', '-c',
-                         mkdir_p.format(join_paths(pkgsysconfdir, 'system/getty.target.wants')))
 meson.add_install_script('sh', '-c',
                          mkdir_p.format(join_paths(pkgsysconfdir, 'user')))
 meson.add_install_script('sh', '-c',
index c83a748456e11e77709976391de1c4fbe69056a5..cfb0a7bc72953a7cf207c4f5406d65902588bcf6 100644 (file)
@@ -320,10 +320,7 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
                 fs->service->n_fd_store--;
         }
 
-        if (fs->event_source) {
-                sd_event_source_set_enabled(fs->event_source, SD_EVENT_OFF);
-                sd_event_source_unref(fs->event_source);
-        }
+        sd_event_source_disable_unref(fs->event_source);
 
         free(fs->fdname);
         safe_close(fs->fd);
index 8440bb27ba88dc90df120069ab37d2a51619ebd2..ba74dc7aea3ab06e3f17f9de0490241da0027c3a 100644 (file)
@@ -430,28 +430,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
 
                         case TIMER_UNIT_ACTIVE:
                                 leave_around = true;
-                                base = trigger->inactive_exit_timestamp.monotonic;
-
-                                if (base <= 0)
-                                        base = t->last_trigger.monotonic;
-
+                                base = MAX(trigger->inactive_exit_timestamp.monotonic, t->last_trigger.monotonic);
                                 if (base <= 0)
                                         continue;
-                                base = MAX(base, t->last_trigger.monotonic);
-
                                 break;
 
                         case TIMER_UNIT_INACTIVE:
                                 leave_around = true;
-                                base = trigger->inactive_enter_timestamp.monotonic;
-
-                                if (base <= 0)
-                                        base = t->last_trigger.monotonic;
-
+                                base = MAX(trigger->inactive_enter_timestamp.monotonic, t->last_trigger.monotonic);
                                 if (base <= 0)
                                         continue;
-                                base = MAX(base, t->last_trigger.monotonic);
-
                                 break;
 
                         default:
diff --git a/src/fuzz/fuzz-varlink.c b/src/fuzz/fuzz-varlink.c
new file mode 100644 (file)
index 0000000..31c13e2
--- /dev/null
@@ -0,0 +1,131 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <unistd.h>
+
+#include "errno-util.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "hexdecoct.h"
+#include "io-util.h"
+#include "varlink.h"
+#include "log.h"
+
+static FILE *null = NULL;
+
+static int method_something(Varlink *v, JsonVariant *p, VarlinkMethodFlags flags, void *userdata) {
+        json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL);
+        return 0;
+}
+
+static int reply_callback(Varlink *v, JsonVariant *p, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+        json_variant_dump(p, JSON_FORMAT_NEWLINE|JSON_FORMAT_PRETTY, null, NULL);
+        return 0;
+}
+
+static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        struct iovec *iov = userdata;
+        bool write_eof = false, read_eof = false;
+
+        assert(s);
+        assert(fd >= 0);
+        assert(iov);
+
+        if ((revents & (EPOLLOUT|EPOLLHUP|EPOLLERR)) && iov->iov_len > 0) {
+                ssize_t n;
+
+                /* never write more than 143 bytes a time, to make broken up recv()s on the other side more
+                 * likely, and thus test some additional code paths. */
+                n = send(fd, iov->iov_base, MIN(iov->iov_len, 143U), MSG_NOSIGNAL|MSG_DONTWAIT);
+                if (n < 0) {
+                        if (ERRNO_IS_DISCONNECT(errno))
+                                write_eof = true;
+                        else
+                                assert_se(errno == EAGAIN);
+                } else
+                        IOVEC_INCREMENT(iov, 1, n);
+        }
+
+        if (revents & EPOLLIN) {
+                char c[137];
+                ssize_t n;
+
+                n = recv(fd, c, sizeof(c), MSG_DONTWAIT);
+                if (n < 0) {
+                        if (ERRNO_IS_DISCONNECT(errno))
+                                read_eof = true;
+                        else
+                                assert_se(errno == EAGAIN);
+                } else if (n == 0)
+                        read_eof = true;
+                else
+                        hexdump(null, c, (size_t) n);
+        }
+
+        /* After we wrote everything we could turn off EPOLLOUT. And if we reached read EOF too turn off the
+         * whole thing. */
+        if (write_eof || iov->iov_len == 0) {
+
+                if (read_eof)
+                        assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
+                else
+                        assert_se(sd_event_source_set_io_events(s, EPOLLIN) >= 0);
+        }
+
+        return 0;
+}
+
+static int idle_callback(sd_event_source *s, void *userdata) {
+        assert(s);
+
+        /* Called as idle callback when there's nothing else to do anymore */
+        sd_event_exit(sd_event_source_get_event(s), 0);
+        return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        struct iovec server_iov = IOVEC_MAKE((void*) data, size), client_iov = IOVEC_MAKE((void*) data, size);
+        /* Important: the declaration order matters here! we want that the fds are closed on return after the
+         * event sources, hence we declare the fds first, the event sources second */
+        _cleanup_close_pair_ int server_pair[2] = { -1, -1 }, client_pair[2] = { -1, -1 };
+        _cleanup_(sd_event_source_unrefp) sd_event_source *idle_event_source = NULL,
+                *server_event_source = NULL, *client_event_source = NULL;
+        _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+
+        log_set_max_level(LOG_CRIT);
+        log_parse_environment();
+
+        assert_se(null = fopen("/dev/null", "we"));
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        /* Test one: write the data as method call to a server */
+        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, server_pair) >= 0);
+        assert_se(varlink_server_new(&s, 0) >= 0);
+        assert_se(varlink_server_set_description(s, "myserver") >= 0);
+        assert_se(varlink_server_attach_event(s, e, 0) >= 0);
+        assert_se(varlink_server_add_connection(s, server_pair[0], NULL) >= 0);
+        TAKE_FD(server_pair[0]);
+        assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
+        assert_se(sd_event_add_io(e, &server_event_source, server_pair[1], EPOLLIN|EPOLLOUT, io_callback, &server_iov) >= 0);
+
+        /* Test two: write the data as method response to a client */
+        assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, client_pair) >= 0);
+        assert_se(varlink_connect_fd(&c, client_pair[0]) >= 0);
+        TAKE_FD(client_pair[0]);
+        assert_se(varlink_set_description(c, "myclient") >= 0);
+        assert_se(varlink_attach_event(c, e, 0) >= 0);
+        assert_se(varlink_bind_reply(c, reply_callback) >= 0);
+        assert_se(varlink_invoke(c, "io.test.DoSomething", NULL) >= 0);
+        assert_se(sd_event_add_io(e, &client_event_source, client_pair[1], EPOLLIN|EPOLLOUT, io_callback, &client_iov) >= 0);
+
+        assert_se(sd_event_add_defer(e, &idle_event_source, idle_callback, NULL) >= 0);
+        assert_se(sd_event_source_set_priority(idle_event_source, SD_EVENT_PRIORITY_IDLE) >= 0);
+
+        assert_se(sd_event_loop(e) >= 0);
+
+        null = safe_fclose(null);
+
+        return 0;
+}
index a6c6db372b170d75fd9d5e864d23f0dadb11b94b..c88812d1de9f7d83a26f7e9c52d19ac875179007 100644 (file)
@@ -51,6 +51,10 @@ fuzzers += [
          [libshared],
          []],
 
+        [['src/fuzz/fuzz-varlink.c'],
+         [libshared],
+         []],
+
         [['src/fuzz/fuzz-unit-file.c'],
          [libcore,
           libshared],
index 83671cf99b04922fa03d2d611334d4214c41319c..febcc43ce87f224797f6a5fcac2f3a6209a90d5c 100644 (file)
@@ -70,8 +70,7 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
                         fd = sd_event_source_get_io_fd(io);
                         assert(fd >= 0);
 
-                        sd_event_source_set_enabled(io, SD_EVENT_OFF);
-                        sd_event_source_unref(io);
+                        sd_event_source_disable_unref(io);
 
                         hashmap_remove(g->ios, FD_TO_PTR(s));
                         hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
index 2321a91e7bd57d0e1a6b0642ca5ab9b2ec9f284e..d32c51c3cec376411797033ce936d412626bdc46 100644 (file)
@@ -528,7 +528,7 @@ static int dispatch_http_event(sd_event_source *event,
                                void *userdata) {
         MHDDaemonWrapper *d = userdata;
         int r;
-        MHD_UNSIGNED_LONG_LONG timeout = ULONG_LONG_MAX;
+        MHD_UNSIGNED_LONG_LONG timeout = ULLONG_MAX;
 
         assert(d);
 
@@ -538,7 +538,7 @@ static int dispatch_http_event(sd_event_source *event,
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "MHD_run failed!");
         if (MHD_get_timeout(d->daemon, &timeout) == MHD_NO)
-                timeout = ULONG_LONG_MAX;
+                timeout = ULLONG_MAX;
 
         r = sd_event_source_set_time(d->timer_event, timeout);
         if (r < 0) {
index 91d1c2921a3f1447ffbe1365d41be4e0dcbeaa38..3e285021bdc90d47276b6d11e972a3971b07e681 100644 (file)
@@ -357,8 +357,7 @@ JournalFile* journal_file_close(JournalFile *f) {
                 if (sd_event_source_get_enabled(f->post_change_timer, NULL) > 0)
                         journal_file_post_change(f);
 
-                (void) sd_event_source_set_enabled(f->post_change_timer, SD_EVENT_OFF);
-                sd_event_source_unref(f->post_change_timer);
+                sd_event_source_disable_unref(f->post_change_timer);
         }
 
         journal_file_set_offline(f, true);
index 0a06ce7b847d11e7807b06328a9891de1fe31fa9..344b7b019a57c3148bccf6c5e1cfa3305ebcb8a6 100644 (file)
@@ -46,7 +46,7 @@ static void draw_progress(uint64_t p, usec_t *last_usec) {
         for (i = 0; i < j; i++)
                 fputs("\xe2\x96\x88", stdout);
 
-        fputs(ANSI_NORMAL, stdout);
+        fputs(ansi_normal(), stdout);
 
         for (i = 0; i < k; i++)
                 fputs("\xe2\x96\x91", stdout);
index 72c162259618b7af778923e37cba1f5611c1ac1e..91a21e407fcedab0595da0719d13b975c35c1468 100644 (file)
@@ -52,6 +52,7 @@
 #include "logs-show.h"
 #include "memory-util.h"
 #include "mkdir.h"
+#include "mountpoint-util.h"
 #include "nulstr-util.h"
 #include "pager.h"
 #include "parse-util.h"
@@ -67,6 +68,7 @@
 #include "tmpfile-util.h"
 #include "unit-name.h"
 #include "user-util.h"
+#include "varlink.h"
 
 #define DEFAULT_FSS_INTERVAL_USEC (15*USEC_PER_MINUTE)
 
@@ -167,6 +169,7 @@ static enum {
         ACTION_UPDATE_CATALOG,
         ACTION_LIST_BOOTS,
         ACTION_FLUSH,
+        ACTION_RELINQUISH_VAR,
         ACTION_SYNC,
         ACTION_ROTATE,
         ACTION_VACUUM,
@@ -368,6 +371,8 @@ static int help(void) {
                "     --vacuum-time=TIME      Remove journal files older than specified time\n"
                "     --verify                Verify journal file consistency\n"
                "     --sync                  Synchronize unwritten journal messages to disk\n"
+               "     --relinquish-var        Stop logging to disk, log to temporary file system\n"
+               "     --smart-relinquish-var  Similar, but NOP if log directory is on root mount\n"
                "     --flush                 Flush all journal data from /run into /var\n"
                "     --rotate                Request immediate rotation of the journal files\n"
                "     --header                Show journal header information\n"
@@ -415,6 +420,8 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_UTC,
                 ARG_SYNC,
                 ARG_FLUSH,
+                ARG_RELINQUISH_VAR,
+                ARG_SMART_RELINQUISH_VAR,
                 ARG_ROTATE,
                 ARG_VACUUM_SIZE,
                 ARG_VACUUM_FILES,
@@ -424,65 +431,67 @@ static int parse_argv(int argc, char *argv[]) {
         };
 
         static const struct option options[] = {
-                { "help",           no_argument,       NULL, 'h'                },
-                { "version" ,       no_argument,       NULL, ARG_VERSION        },
-                { "no-pager",       no_argument,       NULL, ARG_NO_PAGER       },
-                { "pager-end",      no_argument,       NULL, 'e'                },
-                { "follow",         no_argument,       NULL, 'f'                },
-                { "force",          no_argument,       NULL, ARG_FORCE          },
-                { "output",         required_argument, NULL, 'o'                },
-                { "all",            no_argument,       NULL, 'a'                },
-                { "full",           no_argument,       NULL, 'l'                },
-                { "no-full",        no_argument,       NULL, ARG_NO_FULL        },
-                { "lines",          optional_argument, NULL, 'n'                },
-                { "no-tail",        no_argument,       NULL, ARG_NO_TAIL        },
-                { "new-id128",      no_argument,       NULL, ARG_NEW_ID128      }, /* deprecated */
-                { "quiet",          no_argument,       NULL, 'q'                },
-                { "merge",          no_argument,       NULL, 'm'                },
-                { "this-boot",      no_argument,       NULL, ARG_THIS_BOOT      }, /* deprecated */
-                { "boot",           optional_argument, NULL, 'b'                },
-                { "list-boots",     no_argument,       NULL, ARG_LIST_BOOTS     },
-                { "dmesg",          no_argument,       NULL, 'k'                },
-                { "system",         no_argument,       NULL, ARG_SYSTEM         },
-                { "user",           no_argument,       NULL, ARG_USER           },
-                { "directory",      required_argument, NULL, 'D'                },
-                { "file",           required_argument, NULL, ARG_FILE           },
-                { "root",           required_argument, NULL, ARG_ROOT           },
-                { "header",         no_argument,       NULL, ARG_HEADER         },
-                { "identifier",     required_argument, NULL, 't'                },
-                { "priority",       required_argument, NULL, 'p'                },
-                { "grep",           required_argument, NULL, 'g'                },
-                { "case-sensitive", optional_argument, NULL, ARG_CASE_SENSITIVE },
-                { "setup-keys",     no_argument,       NULL, ARG_SETUP_KEYS     },
-                { "interval",       required_argument, NULL, ARG_INTERVAL       },
-                { "verify",         no_argument,       NULL, ARG_VERIFY         },
-                { "verify-key",     required_argument, NULL, ARG_VERIFY_KEY     },
-                { "disk-usage",     no_argument,       NULL, ARG_DISK_USAGE     },
-                { "cursor",         required_argument, NULL, 'c'                },
-                { "cursor-file",    required_argument, NULL, ARG_CURSOR_FILE    },
-                { "after-cursor",   required_argument, NULL, ARG_AFTER_CURSOR   },
-                { "show-cursor",    no_argument,       NULL, ARG_SHOW_CURSOR    },
-                { "since",          required_argument, NULL, 'S'                },
-                { "until",          required_argument, NULL, 'U'                },
-                { "unit",           required_argument, NULL, 'u'                },
-                { "user-unit",      required_argument, NULL, ARG_USER_UNIT      },
-                { "field",          required_argument, NULL, 'F'                },
-                { "fields",         no_argument,       NULL, 'N'                },
-                { "catalog",        no_argument,       NULL, 'x'                },
-                { "list-catalog",   no_argument,       NULL, ARG_LIST_CATALOG   },
-                { "dump-catalog",   no_argument,       NULL, ARG_DUMP_CATALOG   },
-                { "update-catalog", no_argument,       NULL, ARG_UPDATE_CATALOG },
-                { "reverse",        no_argument,       NULL, 'r'                },
-                { "machine",        required_argument, NULL, 'M'                },
-                { "utc",            no_argument,       NULL, ARG_UTC            },
-                { "flush",          no_argument,       NULL, ARG_FLUSH          },
-                { "sync",           no_argument,       NULL, ARG_SYNC           },
-                { "rotate",         no_argument,       NULL, ARG_ROTATE         },
-                { "vacuum-size",    required_argument, NULL, ARG_VACUUM_SIZE    },
-                { "vacuum-files",   required_argument, NULL, ARG_VACUUM_FILES   },
-                { "vacuum-time",    required_argument, NULL, ARG_VACUUM_TIME    },
-                { "no-hostname",    no_argument,       NULL, ARG_NO_HOSTNAME    },
-                { "output-fields",  required_argument, NULL, ARG_OUTPUT_FIELDS  },
+                { "help",                 no_argument,       NULL, 'h'                      },
+                { "version" ,             no_argument,       NULL, ARG_VERSION              },
+                { "no-pager",             no_argument,       NULL, ARG_NO_PAGER             },
+                { "pager-end",            no_argument,       NULL, 'e'                      },
+                { "follow",               no_argument,       NULL, 'f'                      },
+                { "force",                no_argument,       NULL, ARG_FORCE                },
+                { "output",               required_argument, NULL, 'o'                      },
+                { "all",                  no_argument,       NULL, 'a'                      },
+                { "full",                 no_argument,       NULL, 'l'                      },
+                { "no-full",              no_argument,       NULL, ARG_NO_FULL              },
+                { "lines",                optional_argument, NULL, 'n'                      },
+                { "no-tail",              no_argument,       NULL, ARG_NO_TAIL              },
+                { "new-id128",            no_argument,       NULL, ARG_NEW_ID128            }, /* deprecated */
+                { "quiet",                no_argument,       NULL, 'q'                      },
+                { "merge",                no_argument,       NULL, 'm'                      },
+                { "this-boot",            no_argument,       NULL, ARG_THIS_BOOT            }, /* deprecated */
+                { "boot",                 optional_argument, NULL, 'b'                      },
+                { "list-boots",           no_argument,       NULL, ARG_LIST_BOOTS           },
+                { "dmesg",                no_argument,       NULL, 'k'                      },
+                { "system",               no_argument,       NULL, ARG_SYSTEM               },
+                { "user",                 no_argument,       NULL, ARG_USER                 },
+                { "directory",            required_argument, NULL, 'D'                      },
+                { "file",                 required_argument, NULL, ARG_FILE                 },
+                { "root",                 required_argument, NULL, ARG_ROOT                 },
+                { "header",               no_argument,       NULL, ARG_HEADER               },
+                { "identifier",           required_argument, NULL, 't'                      },
+                { "priority",             required_argument, NULL, 'p'                      },
+                { "grep",                 required_argument, NULL, 'g'                      },
+                { "case-sensitive",       optional_argument, NULL, ARG_CASE_SENSITIVE       },
+                { "setup-keys",           no_argument,       NULL, ARG_SETUP_KEYS           },
+                { "interval",             required_argument, NULL, ARG_INTERVAL             },
+                { "verify",               no_argument,       NULL, ARG_VERIFY               },
+                { "verify-key",           required_argument, NULL, ARG_VERIFY_KEY           },
+                { "disk-usage",           no_argument,       NULL, ARG_DISK_USAGE           },
+                { "cursor",               required_argument, NULL, 'c'                      },
+                { "cursor-file",          required_argument, NULL, ARG_CURSOR_FILE          },
+                { "after-cursor",         required_argument, NULL, ARG_AFTER_CURSOR         },
+                { "show-cursor",          no_argument,       NULL, ARG_SHOW_CURSOR          },
+                { "since",                required_argument, NULL, 'S'                      },
+                { "until",                required_argument, NULL, 'U'                      },
+                { "unit",                 required_argument, NULL, 'u'                      },
+                { "user-unit",            required_argument, NULL, ARG_USER_UNIT            },
+                { "field",                required_argument, NULL, 'F'                      },
+                { "fields",               no_argument,       NULL, 'N'                      },
+                { "catalog",              no_argument,       NULL, 'x'                      },
+                { "list-catalog",         no_argument,       NULL, ARG_LIST_CATALOG         },
+                { "dump-catalog",         no_argument,       NULL, ARG_DUMP_CATALOG         },
+                { "update-catalog",       no_argument,       NULL, ARG_UPDATE_CATALOG       },
+                { "reverse",              no_argument,       NULL, 'r'                      },
+                { "machine",              required_argument, NULL, 'M'                      },
+                { "utc",                  no_argument,       NULL, ARG_UTC                  },
+                { "flush",                no_argument,       NULL, ARG_FLUSH                },
+                { "relinquish-var",       no_argument,       NULL, ARG_RELINQUISH_VAR       },
+                { "smart-relinquish-var", no_argument,       NULL, ARG_SMART_RELINQUISH_VAR },
+                { "sync",                 no_argument,       NULL, ARG_SYNC                 },
+                { "rotate",               no_argument,       NULL, ARG_ROTATE               },
+                { "vacuum-size",          required_argument, NULL, ARG_VACUUM_SIZE          },
+                { "vacuum-files",         required_argument, NULL, ARG_VACUUM_FILES         },
+                { "vacuum-time",          required_argument, NULL, ARG_VACUUM_TIME          },
+                { "no-hostname",          no_argument,       NULL, ARG_NO_HOSTNAME          },
+                { "output-fields",        required_argument, NULL, ARG_OUTPUT_FIELDS        },
                 {}
         };
 
@@ -914,6 +923,35 @@ static int parse_argv(int argc, char *argv[]) {
                         arg_action = ACTION_FLUSH;
                         break;
 
+                case ARG_SMART_RELINQUISH_VAR: {
+                        int root_mnt_id, log_mnt_id;
+
+                        /* Try to be smart about relinquishing access to /var/log/journal/ during shutdown:
+                         * if it's on the same mount as the root file system there's no point in
+                         * relinquishing access and we can leave journald write to it until the very last
+                         * moment. */
+
+                        r = path_get_mnt_id("/", &root_mnt_id);
+                        if (r < 0)
+                                log_debug_errno(r, "Failed to get root mount ID, ignoring: %m");
+                        else {
+                                r = path_get_mnt_id("/var/log/journal/", &log_mnt_id);
+                                if (r < 0)
+                                        log_debug_errno(r, "Failed to get journal directory mount ID, ignoring: %m");
+                                else if (root_mnt_id == log_mnt_id) {
+                                        log_debug("/var/log/journal/ is on root file system, not relinquishing access to /var.");
+                                        return 0;
+                                } else
+                                        log_debug("/var/log/journal/ is not on the root file system, relinquishing access to it.");
+                        }
+
+                        _fallthrough_;
+                }
+
+                case ARG_RELINQUISH_VAR:
+                        arg_action = ACTION_RELINQUISH_VAR;
+                        break;
+
                 case ARG_ROTATE:
                         arg_action = arg_action == ACTION_VACUUM ? ACTION_ROTATE_AND_VACUUM : ACTION_ROTATE;
                         break;
@@ -1901,156 +1939,41 @@ static int verify(sd_journal *j) {
         return r;
 }
 
-static int watch_run_systemd_journal(uint32_t mask) {
-        _cleanup_close_ int watch_fd = -1;
-
-        (void) mkdir_p("/run/systemd/journal", 0755);
-
-        watch_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
-        if (watch_fd < 0)
-                return log_error_errno(errno, "Failed to create inotify object: %m");
-
-        if (inotify_add_watch(watch_fd, "/run/systemd/journal", mask) < 0)
-                return log_error_errno(errno, "Failed to watch \"/run/systemd/journal\": %m");
-
-        return TAKE_FD(watch_fd);
-}
-
-static int flush_to_var(void) {
-        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        _cleanup_close_ int watch_fd = -1;
+static int simple_varlink_call(const char *option, const char *method) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *link = NULL;
+        const char *error;
         int r;
 
-        if (arg_machine) {
-                log_error("--flush is not supported in conjunction with --machine=.");
-                return -EOPNOTSUPP;
-        }
-
-        /* Quick exit */
-        if (access("/run/systemd/journal/flushed", F_OK) >= 0)
-                return 0;
+        if (arg_machine)
+                return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "%s is not supported in conjunction with --machine=.", option);
 
-        /* OK, let's actually do the full logic, send SIGUSR1 to the
-         * daemon and set up inotify to wait for the flushed file to appear */
-        r = bus_connect_system_systemd(&bus);
-        if (r < 0)
-                return log_error_errno(r, "Failed to get D-Bus connection: %m");
-
-        r = sd_bus_call_method(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "KillUnit",
-                        &error,
-                        NULL,
-                        "ssi", "systemd-journald.service", "main", SIGUSR1);
+        r = varlink_connect_address(&link, "/run/systemd/journal/io.systemd.journal");
         if (r < 0)
-                return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
+                return log_error_errno(r, "Failed to connect to /run/systemd/journal/io.systemd.journal: %m");
 
-        watch_fd = watch_run_systemd_journal(IN_CREATE|IN_DONT_FOLLOW|IN_ONLYDIR);
-        if (watch_fd < 0)
-                return watch_fd;
+        (void) varlink_set_description(link, "journal");
 
-        for (;;) {
-                if (access("/run/systemd/journal/flushed", F_OK) >= 0)
-                        return 0;
-
-                if (errno != ENOENT)
-                        return log_error_errno(errno, "Failed to check for existence of /run/systemd/journal/flushed: %m");
-
-                r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to wait for event: %m");
+        r = varlink_call(link, method, NULL, NULL, &error, NULL);
+        if (r < 0)
+                return log_error_errno(r, "Failed to execute varlink call: %s", error);
 
-                r = flush_fd(watch_fd);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to flush inotify events: %m");
-        }
+        return 0;
 }
 
-static int send_signal_and_wait(int sig, const char *watch_path) {
-        _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-        _cleanup_close_ int watch_fd = -1;
-        usec_t start;
-        int r;
-
-        if (arg_machine) {
-                log_error("--sync and --rotate are not supported in conjunction with --machine=.");
-                return -EOPNOTSUPP;
-        }
-
-        start = now(CLOCK_MONOTONIC);
-
-        /* This call sends the specified signal to journald, and waits
-         * for acknowledgment by watching the mtime of the specified
-         * flag file. This is used to trigger syncing or rotation and
-         * then wait for the operation to complete. */
-
-        for (;;) {
-                usec_t tstamp;
-
-                /* See if a sync happened by now. */
-                r = read_timestamp_file(watch_path, &tstamp);
-                if (r < 0 && r != -ENOENT)
-                        return log_error_errno(r, "Failed to read %s: %m", watch_path);
-                if (r >= 0 && tstamp >= start)
-                        return 0;
-
-                /* Let's ask for a sync, but only once. */
-                if (!bus) {
-                        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
-
-                        r = bus_connect_system_systemd(&bus);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to get D-Bus connection: %m");
-
-                        r = sd_bus_call_method(
-                                        bus,
-                                        "org.freedesktop.systemd1",
-                                        "/org/freedesktop/systemd1",
-                                        "org.freedesktop.systemd1.Manager",
-                                        "KillUnit",
-                                        &error,
-                                        NULL,
-                                        "ssi", "systemd-journald.service", "main", sig);
-                        if (r < 0)
-                                return log_error_errno(r, "Failed to kill journal service: %s", bus_error_message(&error, r));
-
-                        continue;
-                }
-
-                /* Let's install the inotify watch, if we didn't do that yet. */
-                if (watch_fd < 0) {
-                        watch_fd = watch_run_systemd_journal(IN_MOVED_TO|IN_DONT_FOLLOW|IN_ONLYDIR);
-                        if (watch_fd < 0)
-                                return watch_fd;
-
-                        /* Recheck the flag file immediately, so that we don't miss any event since the last check. */
-                        continue;
-                }
-
-                /* OK, all preparatory steps done, let's wait until inotify reports an event. */
-
-                r = fd_wait_for_event(watch_fd, POLLIN, USEC_INFINITY);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to wait for event: %m");
-
-                r = flush_fd(watch_fd);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to flush inotify events: %m");
-        }
+static int flush_to_var(void) {
+        return simple_varlink_call("--flush", "io.systemd.Journal.FlushToVar");
+}
 
-        return 0;
+static int relinquish_var(void) {
+        return simple_varlink_call("--relinquish-var", "io.systemd.Journal.RelinquishVar");
 }
 
 static int rotate(void) {
-        return send_signal_and_wait(SIGUSR2, "/run/systemd/journal/rotated");
+        return simple_varlink_call("--rotate", "io.systemd.Journal.Rotate");
 }
 
 static int sync_journal(void) {
-        return send_signal_and_wait(SIGRTMIN+1, "/run/systemd/journal/synced");
+        return simple_varlink_call("--sync", "io.systemd.Journal.Synchronize");
 }
 
 static int wait_for_change(sd_journal *j, int poll_fd) {
@@ -2160,6 +2083,10 @@ int main(int argc, char *argv[]) {
                 r = flush_to_var();
                 goto finish;
 
+        case ACTION_RELINQUISH_VAR:
+                r = relinquish_var();
+                goto finish;
+
         case ACTION_SYNC:
                 r = sync_journal();
                 goto finish;
@@ -2751,8 +2678,16 @@ finish:
         free(arg_verify_key);
 
 #if HAVE_PCRE2
-        if (arg_compiled_pattern)
+        if (arg_compiled_pattern) {
                 pcre2_code_free(arg_compiled_pattern);
+
+                /* --grep was used, no error was thrown, but the pattern didn't
+                 * match anything. Let's mimic grep's behavior here and return
+                 * a non-zero exit code, so journalctl --grep can be used
+                 * in scripts and such */
+                if (r == 0 && n_shown == 0)
+                        r = -ENOENT;
+        }
 #endif
 
         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
index ee6c25541cf6445c63a8a0026fa9f32a25564b44..51e7dedad59fce3ff992c6cf7d9a0beb3f021b0e 100644 (file)
@@ -286,13 +286,14 @@ static bool flushed_flag_is_set(void) {
         return access("/run/systemd/journal/flushed", F_OK) >= 0;
 }
 
-static int system_journal_open(Server *s, bool flush_requested) {
+static int system_journal_open(Server *s, bool flush_requested, bool relinquish_requested) {
         const char *fn;
         int r = 0;
 
         if (!s->system_journal &&
             IN_SET(s->storage, STORAGE_PERSISTENT, STORAGE_AUTO) &&
-            (flush_requested || flushed_flag_is_set())) {
+            (flush_requested || flushed_flag_is_set()) &&
+            !relinquish_requested) {
 
                 /* If in auto mode: first try to create the machine
                  * path, but not the prefix.
@@ -334,7 +335,7 @@ static int system_journal_open(Server *s, bool flush_requested) {
 
                 fn = strjoina(s->runtime_storage.path, "/system.journal");
 
-                if (s->system_journal) {
+                if (s->system_journal && !relinquish_requested) {
 
                         /* Try to open the runtime journal, but only
                          * if it already exists, so that we can flush
@@ -389,7 +390,7 @@ static JournalFile* find_journal(Server *s, uid_t uid) {
          * else that's left the journals as NULL).
          *
          * Fixes https://github.com/systemd/systemd/issues/3968 */
-        (void) system_journal_open(s, false);
+        (void) system_journal_open(s, false, false);
 
         /* We split up user logs only on /var, not on /run. If the
          * runtime file is open, we write to it exclusively, in order
@@ -1117,7 +1118,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
         char ts[FORMAT_TIMESPAN_MAX];
         usec_t start;
         unsigned n = 0;
-        int r;
+        int r, k;
 
         assert(s);
 
@@ -1130,7 +1131,7 @@ int server_flush_to_var(Server *s, bool require_flag_file) {
         if (require_flag_file && !flushed_flag_is_set())
                 return 0;
 
-        (void) system_journal_open(s, true);
+        (void) system_journal_open(s, true, false);
 
         if (!s->system_journal)
                 return 0;
@@ -1209,9 +1210,36 @@ finish:
                                           n),
                               NULL);
 
+        k = touch("/run/systemd/journal/flushed");
+        if (k < 0)
+                log_warning_errno(k, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
+
         return r;
 }
 
+static int server_relinquish_var(Server *s) {
+        assert(s);
+
+        if (s->storage == STORAGE_NONE)
+                return 0;
+
+        if (s->runtime_journal && !s->system_journal)
+                return 0;
+
+        log_debug("Relinquishing /var...");
+
+        (void) system_journal_open(s, false, true);
+
+        s->system_journal = journal_file_close(s->system_journal);
+        ordered_hashmap_clear_with_destructor(s->user_journals, journal_file_close);
+        set_clear_with_destructor(s->deferred_closes, journal_file_close);
+
+        if (unlink("/run/systemd/journal/flushed") < 0 && errno != ENOENT)
+                log_warning_errno(errno, "Failed to unlink /run/systemd/journal/flushed, ignoring: %m");
+
+        return 0;
+}
+
 int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
         Server *s = userdata;
         struct ucred *ucred = NULL;
@@ -1330,33 +1358,32 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void
         return 0;
 }
 
-static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
-        Server *s = userdata;
-        int r;
-
+static void server_full_flush(Server *s) {
         assert(s);
 
-        log_info("Received request to flush runtime journal from PID " PID_FMT, si->ssi_pid);
-
         (void) server_flush_to_var(s, false);
         server_sync(s);
         server_vacuum(s, false);
 
-        r = touch("/run/systemd/journal/flushed");
-        if (r < 0)
-                log_warning_errno(r, "Failed to touch /run/systemd/journal/flushed, ignoring: %m");
-
         server_space_usage_message(s, NULL);
-        return 0;
 }
 
-static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+static int dispatch_sigusr1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
         Server *s = userdata;
+
+        assert(s);
+
+        log_info("Received SIGUSR1 signal from PID " PID_FMT ", as request to flush runtime journal.", si->ssi_pid);
+        server_full_flush(s);
+
+        return 0;
+}
+
+static void server_full_rotate(Server *s) {
         int r;
 
         assert(s);
 
-        log_info("Received request to rotate journal from PID " PID_FMT, si->ssi_pid);
         server_rotate(s);
         server_vacuum(s, true);
 
@@ -1369,6 +1396,15 @@ static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *
         r = write_timestamp_file_atomic("/run/systemd/journal/rotated", now(CLOCK_MONOTONIC));
         if (r < 0)
                 log_warning_errno(r, "Failed to write /run/systemd/journal/rotated, ignoring: %m");
+}
+
+static int dispatch_sigusr2(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+        Server *s = userdata;
+
+        assert(s);
+
+        log_info("Received SIGUSR2 signal from PID " PID_FMT ", as request to rotate journal.", si->ssi_pid);
+        server_full_rotate(s);
 
         return 0;
 }
@@ -1384,14 +1420,11 @@ static int dispatch_sigterm(sd_event_source *es, const struct signalfd_siginfo *
         return 0;
 }
 
-static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
-        Server *s = userdata;
+static void server_full_sync(Server *s) {
         int r;
 
         assert(s);
 
-        log_debug("Received request to sync from PID " PID_FMT, si->ssi_pid);
-
         server_sync(s);
 
         /* Let clients know when the most recent sync happened. */
@@ -1399,6 +1432,17 @@ static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo
         if (r < 0)
                 log_warning_errno(r, "Failed to write /run/systemd/journal/synced, ignoring: %m");
 
+        return;
+}
+
+static int dispatch_sigrtmin1(sd_event_source *es, const struct signalfd_siginfo *si, void *userdata) {
+        Server *s = userdata;
+
+        assert(s);
+
+        log_debug("Received SIGRTMIN1 signal from PID " PID_FMT ", as request to sync.", si->ssi_pid );
+        server_full_sync(s);
+
         return 0;
 }
 
@@ -1803,6 +1847,151 @@ static int server_connect_notify(Server *s) {
         return 0;
 }
 
+static int synchronize_second_half(sd_event_source *event_source, void *userdata) {
+        Varlink *link = userdata;
+        Server *s;
+        int r;
+
+        assert(link);
+        assert_se(s = varlink_get_userdata(link));
+
+        /* This is the "second half" of the Synchronize() varlink method. This function is called as deferred
+         * event source at a low priority to ensure the synchronization completes after all queued log
+         * messages are processed. */
+        server_full_sync(s);
+
+        /* Let's get rid of the event source now, by marking it as non-floating again. It then has no ref
+         * anymore and is immediately destroyed after we return from this function, i.e. from this event
+         * source handler at the end. */
+        r = sd_event_source_set_floating(event_source, false);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mark event source as non-floating: %m");
+
+        return varlink_reply(link, NULL);
+}
+
+static void synchronize_destroy(void *userdata) {
+        varlink_unref(userdata);
+}
+
+static int vl_method_synchronize(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *event_source = NULL;
+        Server *s = userdata;
+        int r;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to rotate journal.");
+
+        /* We don't do the main work now, but instead enqueue a deferred event loop job which will do
+         * it. That job is scheduled at low priority, so that we return from this method call only after all
+         * queued but not processed log messages are written to disk, so that this method call returning can
+         * be used as nice synchronization point. */
+        r = sd_event_add_defer(s->event, &event_source, synchronize_second_half, link);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate defer event source: %m");
+
+        r = sd_event_source_set_destroy_callback(event_source, synchronize_destroy);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set event source destroy callback: %m");
+
+        varlink_ref(link); /* The varlink object is now left to the destroy callack to unref */
+
+        r = sd_event_source_set_priority(event_source, SD_EVENT_PRIORITY_NORMAL+15);
+        if (r < 0)
+                return log_error_errno(r, "Failed to set defer event source priority: %m");
+
+        /* Give up ownership of this event source. It will now be destroyed along with event loop itself,
+         * unless it destroys itself earlier. */
+        r = sd_event_source_set_floating(event_source, true);
+        if (r < 0)
+                return log_error_errno(r, "Failed to mark event source as floating: %m");
+
+        (void) sd_event_source_set_description(event_source, "deferred-sync");
+
+        return 0;
+}
+
+static int vl_method_rotate(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to rotate journal.");
+        server_full_rotate(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int vl_method_flush_to_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to flush runtime journal.");
+        server_full_flush(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int vl_method_relinquish_var(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        Server *s = userdata;
+
+        assert(link);
+        assert(s);
+
+        if (json_variant_elements(parameters) > 0)
+                return varlink_error_invalid_parameter(link, parameters);
+
+        log_info("Received client request to relinquish /var access.");
+        server_relinquish_var(s);
+
+        return varlink_reply(link, NULL);
+}
+
+static int server_open_varlink(Server *s) {
+        int r;
+
+        assert(s);
+
+        r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY);
+        if (r < 0)
+                return r;
+
+        varlink_server_set_userdata(s->varlink_server, s);
+
+        r = varlink_server_bind_method_many(
+                        s->varlink_server,
+                        "io.systemd.Journal.Synchronize",   vl_method_synchronize,
+                        "io.systemd.Journal.Rotate",        vl_method_rotate,
+                        "io.systemd.Journal.FlushToVar",    vl_method_flush_to_var,
+                        "io.systemd.Journal.RelinquishVar", vl_method_relinquish_var);
+        if (r < 0)
+                return r;
+
+        r = varlink_server_listen_address(s->varlink_server, "/run/systemd/journal/io.systemd.journal", 0600);
+        if (r < 0)
+                return r;
+
+        r = varlink_server_attach_event(s->varlink_server, s->event, SD_EVENT_PRIORITY_NORMAL);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
 int server_init(Server *s) {
         _cleanup_fdset_free_ FDSet *fds = NULL;
         int n, r, fd;
@@ -1973,6 +2162,10 @@ int server_init(Server *s) {
                         return r;
         }
 
+        r = server_open_varlink(s);
+        if (r < 0)
+                return r;
+
         r = server_open_kernel_seqnum(s);
         if (r < 0)
                 return r;
@@ -2006,7 +2199,7 @@ int server_init(Server *s) {
 
         (void) client_context_acquire_default(s);
 
-        return system_journal_open(s, false);
+        return system_journal_open(s, false, false);
 }
 
 void server_maybe_append_tags(Server *s) {
@@ -2043,6 +2236,8 @@ void server_done(Server *s) {
 
         ordered_hashmap_free_with_destructor(s->user_journals, journal_file_close);
 
+        varlink_server_unref(s->varlink_server);
+
         sd_event_source_unref(s->syslog_event_source);
         sd_event_source_unref(s->native_event_source);
         sd_event_source_unref(s->stdout_event_source);
index 5f0b3dd4ac2a8a98c745dab65ea3fc374841a441..6ce9f269ffc5b294567823337222faaf5bb391d1 100644 (file)
@@ -17,6 +17,7 @@ typedef struct Server Server;
 #include "list.h"
 #include "prioq.h"
 #include "time-util.h"
+#include "varlink.h"
 
 typedef enum Storage {
         STORAGE_AUTO,
@@ -166,6 +167,8 @@ struct Server {
 
         ClientContext *my_context; /* the context of journald itself */
         ClientContext *pid1_context; /* the context of PID 1 */
+
+        VarlinkServer *varlink_server;
 };
 
 #define SERVER_MACHINE_ID(s) ((s)->machine_id_field + STRLEN("_MACHINE_ID="))
index 33a8ef799975bef06b05b11b1b87d41427efb3f1..6e077c0860c543857b918b7fd811ecc7b0fe701b 100644 (file)
@@ -532,7 +532,7 @@ int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempt
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
 
-        if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
+        if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
                 return -EADDRNOTAVAIL;
 
         if (ret)
@@ -541,11 +541,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         return 0;
 }
 
-static void client_notify(sd_dhcp_client *client, int event) {
+static int client_notify(sd_dhcp_client *client, int event) {
         assert(client);
 
         if (client->callback)
-                client->callback(client, event, client->userdata);
+                return client->callback(client, event, client->userdata);
+
+        return 0;
 }
 
 static int client_initialize(sd_dhcp_client *client) {
@@ -604,7 +606,7 @@ static int client_message_init(
         assert(ret);
         assert(_optlen);
         assert(_optoffset);
-        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
+        assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
 
         optlen = DHCP_MIN_OPTIONS_SIZE;
         size = sizeof(DHCPPacket) + optlen;
@@ -695,7 +697,7 @@ static int client_message_init(
            MAY contain the Parameter Request List option. */
         /* NOTE: in case that there would be an option to do not send
          * any PRL at all, the size should be checked before sending */
-        if (client->req_opts_size > 0) {
+        if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
                                        SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
                                        client->req_opts_size, client->req_opts);
@@ -727,7 +729,7 @@ static int client_message_init(
          */
         /* RFC7844 section 3:
            SHOULD NOT contain any other option. */
-        if (!client->anonymize) {
+        if (!client->anonymize && type != DHCP_RELEASE) {
                 max_size = htobe16(size);
                 r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
                                        SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
@@ -859,6 +861,41 @@ static int client_send_discover(sd_dhcp_client *client) {
         return 0;
 }
 
+static int client_send_release(sd_dhcp_client *client) {
+        _cleanup_free_ DHCPPacket *release = NULL;
+        size_t optoffset, optlen;
+        int r;
+
+        assert(client);
+        assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
+
+        r = client_message_init(client, &release, DHCP_RELEASE,
+                                &optlen, &optoffset);
+        if (r < 0)
+                return r;
+
+        /* Fill up release IP and MAC */
+        release->dhcp.ciaddr = client->lease->address;
+        memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
+
+        r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
+                               SD_DHCP_OPTION_END, 0, NULL);
+        if (r < 0)
+                return r;
+
+        r = dhcp_network_send_udp_socket(client->fd,
+                                         client->lease->server_address,
+                                         DHCP_PORT_SERVER,
+                                         &release->dhcp,
+                                         sizeof(DHCPMessage) + optoffset);
+        if (r < 0)
+                return r;
+
+        log_dhcp_client(client, "RELEASE");
+
+        return 0;
+}
+
 static int client_send_request(sd_dhcp_client *client) {
         _cleanup_free_ DHCPPacket *request = NULL;
         size_t optoffset, optlen;
@@ -1328,6 +1365,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
         sd_dhcp_lease_unref(client->lease);
         client->lease = TAKE_PTR(lease);
 
+        if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
+                return -ENOMSG;
+
         log_dhcp_client(client, "OFFER");
 
         return 0;
@@ -1853,6 +1893,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
         return r;
 }
 
+int sd_dhcp_client_send_release(sd_dhcp_client *client) {
+        assert_return(client, -EINVAL);
+
+        client_send_release(client);
+
+        return 0;
+}
+
 int sd_dhcp_client_stop(sd_dhcp_client *client) {
         DHCP_CLIENT_DONT_DESTROY(client);
 
index 0431e2c3f568605ed2d3e12e8cdd2d6d154b74a1..5f31d24d20bd4d3e750d5bd88d02a9c835909746 100644 (file)
@@ -418,7 +418,7 @@ static uint8_t test_addr_acq_ack[] = {
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
-static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
+static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
                                    void *userdata) {
         sd_event *e = userdata;
         sd_dhcp_lease *lease;
@@ -426,7 +426,7 @@ static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
         const struct in_addr *addrs;
 
         assert_se(client);
-        assert_se(event == SD_DHCP_CLIENT_EVENT_IP_ACQUIRE);
+        assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
 
         assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
         assert_se(lease);
@@ -447,6 +447,8 @@ static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
                 printf("  DHCP address acquired\n");
 
         sd_event_exit(e, 0);
+
+        return 0;
 }
 
 static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
index a9ab0605ce14427d8b0219e91d7b0014fd1b14a9..5ec42e0f1f826eb602ce121e2650012b3250f930 100644 (file)
@@ -680,4 +680,5 @@ global:
 LIBSYSTEMD_243 {
 global:
         sd_bus_object_vtable_format;
+        sd_event_source_disable_unref;
 } LIBSYSTEMD_241;
index 50017a9517baac9ef06934413ac0c443e30ef521..09285c19d86b6d29047128a2be01e2ee3c0bc13b 100644 (file)
@@ -339,6 +339,12 @@ fail:
 
 DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
 
+_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
+        if (s)
+                (void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
+        return sd_event_source_unref(s);
+}
+
 static bool event_pid_changed(sd_event *e) {
         assert(e);
 
index 192033fd696eb6cfc17024b5513ab09fcf5e0736..0a6bd330025eaade54bb97760c68336e6fbab295 100644 (file)
@@ -301,6 +301,8 @@ static const NLType rtnl_link_info_data_geneve_types[] = {
         [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
         [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
         [IFLA_GENEVE_LABEL]             = { .type = NETLINK_TYPE_U32 },
+        [IFLA_GENEVE_TTL_INHERIT]       = { .type = NETLINK_TYPE_U8 },
+        [IFLA_GENEVE_DF]                = { .type = NETLINK_TYPE_U8 },
 };
 
 static const NLType rtnl_link_info_data_can_types[] = {
@@ -335,6 +337,7 @@ static const char* const nl_union_link_info_data_table[] = {
         [NL_UNION_LINK_INFO_DATA_MACVLAN] = "macvlan",
         [NL_UNION_LINK_INFO_DATA_MACVTAP] = "macvtap",
         [NL_UNION_LINK_INFO_DATA_IPVLAN] = "ipvlan",
+        [NL_UNION_LINK_INFO_DATA_IPVTAP] = "ipvtap",
         [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
         [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
@@ -373,6 +376,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
                                                        .types = rtnl_link_info_data_macvlan_types },
         [NL_UNION_LINK_INFO_DATA_IPVLAN] =           { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
                                                        .types = rtnl_link_info_data_ipvlan_types },
+        [NL_UNION_LINK_INFO_DATA_IPVTAP] =           { .count = ELEMENTSOF(rtnl_link_info_data_ipvlan_types),
+                                                       .types = rtnl_link_info_data_ipvlan_types },
         [NL_UNION_LINK_INFO_DATA_VXLAN] =            { .count = ELEMENTSOF(rtnl_link_info_data_vxlan_types),
                                                        .types = rtnl_link_info_data_vxlan_types },
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] =      { .count = ELEMENTSOF(rtnl_link_info_data_iptun_types),
@@ -585,20 +590,22 @@ static const NLTypeSystem rtnl_address_type_system = {
 /* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
 
 static const NLType rtnl_route_metrics_types[] = {
-        [RTAX_MTU]               = { .type = NETLINK_TYPE_U32 },
-        [RTAX_WINDOW]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTT]               = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTTVAR]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_SSTHRESH]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_CWND]              = { .type = NETLINK_TYPE_U32 },
-        [RTAX_ADVMSS]            = { .type = NETLINK_TYPE_U32 },
-        [RTAX_REORDERING]        = { .type = NETLINK_TYPE_U32 },
-        [RTAX_HOPLIMIT]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITCWND]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_FEATURES]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_RTO_MIN]           = { .type = NETLINK_TYPE_U32 },
-        [RTAX_INITRWND]          = { .type = NETLINK_TYPE_U32 },
-        [RTAX_QUICKACK]          = { .type = NETLINK_TYPE_U32 },
+        [RTAX_MTU]                = { .type = NETLINK_TYPE_U32 },
+        [RTAX_WINDOW]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTT]                = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTTVAR]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_SSTHRESH]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_CWND]               = { .type = NETLINK_TYPE_U32 },
+        [RTAX_ADVMSS]             = { .type = NETLINK_TYPE_U32 },
+        [RTAX_REORDERING]         = { .type = NETLINK_TYPE_U32 },
+        [RTAX_HOPLIMIT]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_INITCWND]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_FEATURES]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_RTO_MIN]            = { .type = NETLINK_TYPE_U32 },
+        [RTAX_INITRWND]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_QUICKACK]           = { .type = NETLINK_TYPE_U32 },
+        [RTAX_CC_ALGO]            = { .type = NETLINK_TYPE_U32 },
+        [RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 },
 };
 
 static const NLTypeSystem rtnl_route_metrics_type_system = {
@@ -615,23 +622,23 @@ static const NLType rtnl_route_types[] = {
         [RTA_PRIORITY]          = { .type = NETLINK_TYPE_U32 },
         [RTA_PREFSRC]           = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
         [RTA_METRICS]           = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system},
-/*      [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
-*/
+        [RTA_MULTIPATH]         = { .size = sizeof(struct rtnexthop) },
         [RTA_FLOW]              = { .type = NETLINK_TYPE_U32 }, /* 6? */
-/*
-        RTA_CACHEINFO,
-        RTA_TABLE,
-        RTA_MARK,
-        RTA_MFC_STATS,
-        RTA_VIA,
-        RTA_NEWDST,
-*/
+        [RTA_CACHEINFO]         = { .size = sizeof(struct rta_cacheinfo) },
+        [RTA_TABLE]             = { .type = NETLINK_TYPE_U32 },
+        [RTA_MARK]              = { .type = NETLINK_TYPE_U32 },
+        [RTA_MFC_STATS]         = { .type = NETLINK_TYPE_U64 },
+        [RTA_VIA]               = { .type = NETLINK_TYPE_U32 },
+        [RTA_NEWDST]            = { .type = NETLINK_TYPE_U32 },
         [RTA_PREF]              = { .type = NETLINK_TYPE_U8 },
-/*
-        RTA_ENCAP_TYPE,
-        RTA_ENCAP,
- */
         [RTA_EXPIRES]           = { .type = NETLINK_TYPE_U32 },
+        [RTA_ENCAP_TYPE]        = { .type = NETLINK_TYPE_U16 },
+        [RTA_ENCAP]             = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
+        [RTA_UID]               = { .type = NETLINK_TYPE_U32 },
+        [RTA_TTL_PROPAGATE]     = { .type = NETLINK_TYPE_U8 },
+        [RTA_IP_PROTO]          = { .type = NETLINK_TYPE_U8 },
+        [RTA_SPORT]             = { .type = NETLINK_TYPE_U16 },
+        [RTA_DPORT]             = { .type = NETLINK_TYPE_U16 },
 };
 
 static const NLTypeSystem rtnl_route_type_system = {
@@ -796,6 +803,12 @@ static const NLType genl_fou_types[] = {
         [FOU_ATTR_IPPROTO]           = { .type = NETLINK_TYPE_U8 },
         [FOU_ATTR_TYPE]              = { .type = NETLINK_TYPE_U8 },
         [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
+        [FOU_ATTR_LOCAL_V4]          = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_PEER_V4]           = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_LOCAL_V6]          = { .type = NETLINK_TYPE_IN_ADDR },
+        [FOU_ATTR_PEER_V6]           = { .type = NETLINK_TYPE_IN_ADDR},
+        [FOU_ATTR_PEER_PORT]         = { .type = NETLINK_TYPE_U16},
+        [FOU_ATTR_IFINDEX]           = { .type = NETLINK_TYPE_U32},
 };
 
 static const NLTypeSystem genl_fou_type_system = {
index a2b3087d1596158dd748e56b55fe629724ff1c8a..8585280463a647bf22d3beca634d92a945c0adb0 100644 (file)
@@ -62,6 +62,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_MACVLAN,
         NL_UNION_LINK_INFO_DATA_MACVTAP,
         NL_UNION_LINK_INFO_DATA_IPVLAN,
+        NL_UNION_LINK_INFO_DATA_IPVTAP,
         NL_UNION_LINK_INFO_DATA_VXLAN,
         NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
index 2acbe858bb5a52b44937a4ad87af405c5c77893a..0bcf7f4a815d193f510c909931e67d33a34e963e 100644 (file)
@@ -49,6 +49,8 @@ sources = files('''
         networkd-address.h
         networkd-brvlan.c
         networkd-brvlan.h
+        networkd-can.c
+        networkd-can.h
         networkd-conf.c
         networkd-conf.h
         networkd-dhcp4.c
@@ -61,6 +63,8 @@ sources = files('''
         networkd-link-bus.c
         networkd-link.c
         networkd-link.h
+        networkd-lldp-rx.c
+        networkd-lldp-rx.h
         networkd-lldp-tx.c
         networkd-lldp-tx.h
         networkd-manager-bus.c
index 166aa37139fd6b6752011cd33ce80c872e985645..240cfe34e223e15569c3975323f1b249fd75019a 100644 (file)
@@ -7,6 +7,8 @@
 #include "conf-parser.h"
 #include "ether-addr-util.h"
 #include "extract-word.h"
+#include "netlink-util.h"
+#include "networkd-manager.h"
 #include "string-table.h"
 #include "string-util.h"
 
@@ -291,6 +293,78 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
         return 0;
 }
 
+static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(m);
+        assert(link);
+        assert(link->ifname);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not set bonding interface: %m");
+                return 1;
+        }
+
+        return 1;
+}
+
+int link_set_bond(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+        r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+        r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        if (link->network->active_slave) {
+                r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
+        }
+
+        if (link->network->primary_slave) {
+                r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r,  "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return r;
+}
+
 int config_parse_arp_ip_target_address(
                 const char *unit,
                 const char *filename,
index 12f59cd94695c57c883dd1e2ebf53e716af63eea..28796a3a8be1d40ff75893c64c4a2b9442830b49 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_bonding.h>
 
 #include "in-addr-util.h"
@@ -119,6 +120,8 @@ typedef struct Bond {
 DEFINE_NETDEV_CAST(BOND, Bond);
 extern const NetDevVTable bond_vtable;
 
+int link_set_bond(Link *link);
+
 const char *bond_mode_to_string(BondMode d) _const_;
 BondMode bond_mode_from_string(const char *d) _pure_;
 
index cbbf11220be523a17d8f5aca457aa20336786a50..f20130d26441f813496561e611d0ad52ed4703c5 100644 (file)
@@ -5,9 +5,22 @@
 #include "missing.h"
 #include "netlink-util.h"
 #include "netdev/bridge.h"
+#include "network-internal.h"
 #include "networkd-manager.h"
+#include "string-table.h"
 #include "vlan-util.h"
 
+static const char* const multicast_router_table[_MULTICAST_ROUTER_MAX] = {
+        [MULTICAST_ROUTER_NONE] = "no",
+        [MULTICAST_ROUTER_TEMPORARY_QUERY] = "query",
+        [MULTICAST_ROUTER_PERMANENT] = "permanent",
+        [MULTICAST_ROUTER_TEMPORARY] = "temporary",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(multicast_router, MulticastRouter, _MULTICAST_ROUTER_INVALID);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_multicast_router, multicast_router, MulticastRouter,
+                         "Failed to parse bridge multicast router setting");
+
 /* callback for bridge netdev's parameter set */
 static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
         int r;
@@ -138,6 +151,142 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
         return r;
 }
 
+static int link_set_bridge_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(m);
+        assert(link);
+        assert(link->ifname);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not set bridge interface: %m");
+                return 1;
+        }
+
+        return 1;
+}
+
+int link_set_bridge(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set message family: %m");
+
+        r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+
+        if (link->network->use_bpdu >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
+        }
+
+        if (link->network->hairpin >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
+        }
+
+        if (link->network->fast_leave >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
+        }
+
+        if (link->network->allow_port_to_be_root >=  0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
+        }
+
+        if (link->network->unicast_flood >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+        }
+
+        if (link->network->multicast_flood >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
+        }
+
+        if (link->network->multicast_to_unicast >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
+        }
+
+        if (link->network->neighbor_suppression >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
+        }
+
+        if (link->network->learning >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
+        }
+
+        if (link->network->bridge_proxy_arp >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP, link->network->bridge_proxy_arp);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP attribute: %m");
+        }
+
+        if (link->network->bridge_proxy_arp_wifi >= 0) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROXYARP_WIFI, link->network->bridge_proxy_arp_wifi);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROXYARP_WIFI attribute: %m");
+        }
+
+        if (link->network->cost != 0) {
+                r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
+        }
+
+        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
+                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
+        }
+
+        if (link->network->multicast_router != _MULTICAST_ROUTER_INVALID) {
+                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MULTICAST_ROUTER, link->network->multicast_router);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MULTICAST_ROUTER attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(req);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bridge_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return r;
+}
+
 static void bridge_init(NetDev *n) {
         Bridge *b;
 
index 3edc93a767a3fdefd34c980f95881505bece1c44..2954155c373928a382fb9c3c6b4d685cc33d9993 100644 (file)
@@ -1,7 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include "netdev/netdev.h"
+#include <netinet/in.h>
+#include <linux/if_bridge.h>
+
+#include "conf-parser.h"
+#include "netdev.h"
 
 typedef struct Bridge {
         NetDev meta;
@@ -20,5 +24,21 @@ typedef struct Bridge {
         usec_t ageing_time;
 } Bridge;
 
+typedef enum MulticastRouter {
+        MULTICAST_ROUTER_NONE            = MDB_RTR_TYPE_DISABLED,
+        MULTICAST_ROUTER_TEMPORARY_QUERY = MDB_RTR_TYPE_TEMP_QUERY,
+        MULTICAST_ROUTER_PERMANENT       = MDB_RTR_TYPE_PERM,
+        MULTICAST_ROUTER_TEMPORARY       = MDB_RTR_TYPE_TEMP,
+        _MULTICAST_ROUTER_MAX,
+        _MULTICAST_ROUTER_INVALID = -1,
+} MulticastRouter;
+
 DEFINE_NETDEV_CAST(BRIDGE, Bridge);
 extern const NetDevVTable bridge_vtable;
+
+int link_set_bridge(Link *link);
+
+const char* multicast_router_to_string(MulticastRouter i) _const_;
+MulticastRouter multicast_router_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_multicast_router);
index 2d4481e0602d7add39183caa6952205f3ad11e58..772f3db5e7b483584695b788ba5268966bc19cc7 100644 (file)
@@ -1,7 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <linux/fou.h>
 #include <net/if.h>
+#include <netinet/in.h>
 #include <linux/ip.h>
 
 #include "conf-parser.h"
@@ -46,6 +47,12 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PORT attribute: %m");
 
+        if (IN_SET(t->peer_family, AF_INET, AF_INET6)) {
+                r = sd_netlink_message_append_u16(m, FOU_ATTR_PEER_PORT, htobe16(t->peer_port));
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_PORT attribute: %m");
+        }
+
         switch (t->fou_encap_type) {
         case NETDEV_FOO_OVER_UDP_ENCAP_DIRECT:
                 encap_type = FOU_ENCAP_DIRECT;
@@ -69,6 +76,26 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_IPPROTO attribute: %m");
 
+        if (t->local_family == AF_INET) {
+                r = sd_netlink_message_append_in_addr(m, FOU_ATTR_LOCAL_V4, &t->local.in);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V4 attribute: %m");
+        } else if (t->local_family == AF_INET6) {
+                r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_LOCAL_V6, &t->local.in6);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_LOCAL_V6 attribute: %m");
+        }
+
+        if (t->peer_family == AF_INET) {
+                r = sd_netlink_message_append_in_addr(m, FOU_ATTR_PEER_V4, &t->peer.in);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V4 attribute: %m");
+        } else if (t->peer_family == AF_INET6){
+                r = sd_netlink_message_append_in6_addr(m, FOU_ATTR_PEER_V6, &t->peer.in6);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append FOU_ATTR_PEER_V6 attribute: %m");
+        }
+
         *ret = TAKE_PTR(m);
         return 0;
 }
@@ -150,6 +177,41 @@ int config_parse_ip_protocol(
         return 0;
 }
 
+int config_parse_fou_tunnel_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) {
+
+        union in_addr_union *addr = data;
+        FouTunnel *t = userdata;
+        int r, *f;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(lvalue, "Local"))
+                f = &t->local_family;
+        else
+                f = &t->peer_family;
+
+        r = in_addr_from_string_auto(rvalue, f, addr);
+        if (r < 0)
+                log_syntax(unit, LOG_ERR, filename, line, r,
+                           "Foo over UDP tunnel '%s' address is invalid, ignoring assignment: %s",
+                           lvalue, rvalue);
+
+        return 0;
+}
+
 static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
         FouTunnel *t;
 
@@ -177,6 +239,14 @@ static int netdev_fou_tunnel_verify(NetDev *netdev, const char *filename) {
                 assert_not_reached("Invalid fou encap type");
         }
 
+        if (t->peer_family == AF_UNSPEC && t->peer_port > 0)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "FooOverUDP peer port is set but peer address not configured in %s. Rejecting configuration.",
+                                              filename);
+        else if (t->peer_family != AF_UNSPEC && t->peer_port == 0)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "FooOverUDP peer port not set but peer address is configured in %s. Rejecting configuration.",
+                                              filename);
         return 0;
 }
 
index 51eeac41bd237e46e50bef874ae0770793757e98..6304e6b54927ea7ac6bae6d417ce376d90190a9f 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/fou.h>
 
 #include "in-addr-util.h"
@@ -20,8 +21,14 @@ typedef struct FouTunnel {
         uint8_t fou_protocol;
 
         uint16_t port;
+        uint16_t peer_port;
+
+        int local_family;
+        int peer_family;
 
         FooOverUDPEncapType fou_encap_type;
+        union in_addr_union local;
+        union in_addr_union peer;
 } FouTunnel;
 
 DEFINE_NETDEV_CAST(FOU, FouTunnel);
@@ -32,3 +39,4 @@ FooOverUDPEncapType fou_encap_type_from_string(const char *d) _pure_;
 
 CONFIG_PARSER_PROTOTYPE(config_parse_fou_encap_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_ip_protocol);
+CONFIG_PARSER_PROTOTYPE(config_parse_fou_tunnel_address);
index 0fb09961d626e55f1a49ae3b04b0359b5edf7a64..3dc8f083cc64709395d8ac7cbc21540344d37dcc 100644 (file)
@@ -10,6 +10,7 @@
 #include "geneve.h"
 #include "netlink-util.h"
 #include "parse-util.h"
+#include "string-table.h"
 #include "string-util.h"
 #include "strv.h"
 #include "missing.h"
 #define GENEVE_FLOW_LABEL_MAX_MASK 0xFFFFFU
 #define DEFAULT_GENEVE_DESTINATION_PORT 6081
 
+static const char* const geneve_df_table[_NETDEV_GENEVE_DF_MAX] = {
+        [NETDEV_GENEVE_DF_NO] = "no",
+        [NETDEV_GENEVE_DF_YES] = "yes",
+        [NETDEV_GENEVE_DF_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(geneve_df, GeneveDF, NETDEV_GENEVE_DF_YES);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_geneve_df, geneve_df, GeneveDF, "Failed to parse Geneve IPDoNotFragment= setting");
+
 /* callback for geneve netdev's created without a backing Link */
 static int geneve_netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, NetDev *netdev) {
         int r;
@@ -92,7 +102,11 @@ static int netdev_geneve_create(NetDev *netdev) {
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_REMOTE/IFLA_GENEVE_REMOTE6 attribute: %m");
         }
 
-        if (v->ttl > 0) {
+        if (v->inherit) {
+                r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL_INHERIT, 1);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL_INHERIT attribute: %m");
+        } else {
                 r = sd_netlink_message_append_u8(m, IFLA_GENEVE_TTL, v->ttl);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_TTL attribute: %m");
@@ -126,6 +140,12 @@ static int netdev_geneve_create(NetDev *netdev) {
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_LABEL attribute: %m");
         }
 
+        if (v->geneve_df != _NETDEV_GENEVE_DF_INVALID) {
+                r = sd_netlink_message_append_u8(m, IFLA_GENEVE_DF, v->geneve_df);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_GENEVE_DF attribute: %m");
+        }
+
         r = sd_netlink_message_close_container(m);
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
@@ -255,6 +275,47 @@ int config_parse_geneve_flow_label(const char *unit,
         return 0;
 }
 
+int config_parse_geneve_ttl(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) {
+        Geneve *v = userdata;
+        unsigned f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "inherit"))
+                v->inherit = true;
+        else {
+                r = safe_atou(rvalue, &f);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse Geneve TTL '%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+
+                if (f > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid Geneve TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
+                        return 0;
+                }
+
+                v->ttl = f;
+        }
+
+        return 0;
+}
+
 static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
         Geneve *v = GENEVE(netdev);
 
@@ -262,10 +323,10 @@ static int netdev_geneve_verify(NetDev *netdev, const char *filename) {
         assert(v);
         assert(filename);
 
-        if (v->ttl == 0) {
-                log_warning("Invalid Geneve TTL value '0' configured in '%s'. Ignoring", filename);
-                return -EINVAL;
-        }
+        if (v->id > GENEVE_VID_MAX)
+                return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                                "%s: Geneve without valid VNI (or Virtual Network Identifier) configured. Ignoring.",
+                                                filename);
 
         return 0;
 }
@@ -280,6 +341,7 @@ static void geneve_init(NetDev *netdev) {
         assert(v);
 
         v->id = GENEVE_VID_MAX + 1;
+        v->geneve_df = _NETDEV_GENEVE_DF_INVALID;
         v->dest_port = DEFAULT_GENEVE_DESTINATION_PORT;
         v->udpcsum = false;
         v->udp6zerocsumtx = false;
index c201981e02110b62b270c06d5c2c19a73d8baa8c..32f7f038ba05551ab01a7b024a9b58b57ba8f3d6 100644 (file)
@@ -10,6 +10,14 @@ typedef struct Geneve Geneve;
 
 #define GENEVE_VID_MAX (1u << 24) - 1
 
+typedef enum GeneveDF {
+        NETDEV_GENEVE_DF_NO = GENEVE_DF_UNSET,
+        NETDEV_GENEVE_DF_YES = GENEVE_DF_SET,
+        NETDEV_GENEVE_DF_INHERIT = GENEVE_DF_INHERIT,
+        _NETDEV_GENEVE_DF_MAX,
+        _NETDEV_GENEVE_DF_INVALID = -1
+} GeneveDF;
+
 struct Geneve {
         NetDev meta;
 
@@ -26,13 +34,20 @@ struct Geneve {
         bool udpcsum;
         bool udp6zerocsumtx;
         bool udp6zerocsumrx;
+        bool inherit;
 
+        GeneveDF geneve_df;
         union in_addr_union remote;
 };
 
 DEFINE_NETDEV_CAST(GENEVE, Geneve);
 extern const NetDevVTable geneve_vtable;
 
+const char *geneve_df_to_string(GeneveDF d) _const_;
+GeneveDF geneve_df_from_string(const char *d) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_vni);
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_geneve_flow_label);
+CONFIG_PARSER_PROTOTYPE(config_parse_geneve_df);
+CONFIG_PARSER_PROTOTYPE(config_parse_geneve_ttl);
index 5bb6a5bb35b7a6c421c40f43dd1537266035bc7d..7b2517676729ff4bf4b6b30bcda51689e0ba86fa 100644 (file)
@@ -32,7 +32,10 @@ static int netdev_ipvlan_fill_message_create(NetDev *netdev, Link *link, sd_netl
         assert(link);
         assert(netdev->ifname);
 
-        m = IPVLAN(netdev);
+        if (netdev->kind == NETDEV_KIND_IPVLAN)
+                m = IPVLAN(netdev);
+        else
+                m = IPVTAP(netdev);
 
         assert(m);
 
@@ -56,7 +59,10 @@ static void ipvlan_init(NetDev *n) {
 
         assert(n);
 
-        m = IPVLAN(n);
+        if (n->kind == NETDEV_KIND_IPVLAN)
+                m = IPVLAN(n);
+        else
+                m = IPVTAP(n);
 
         assert(m);
 
@@ -71,3 +77,11 @@ const NetDevVTable ipvlan_vtable = {
         .fill_message_create = netdev_ipvlan_fill_message_create,
         .create_type = NETDEV_CREATE_STACKED,
 };
+
+const NetDevVTable ipvtap_vtable = {
+        .object_size = sizeof(IPVlan),
+        .init = ipvlan_init,
+        .sections = "Match\0NetDev\0IPVTAP\0",
+        .fill_message_create = netdev_ipvlan_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED,
+};
index 78f09dbb2d58a9915424bbc37239aaa579e51c52..140cacf4fcbdfda2bedadac1fc4a2921b60caa86 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_link.h>
 
 #include "netdev/netdev.h"
@@ -29,7 +30,9 @@ typedef struct IPVlan {
 } IPVlan;
 
 DEFINE_NETDEV_CAST(IPVLAN, IPVlan);
+DEFINE_NETDEV_CAST(IPVTAP, IPVlan);
 extern const NetDevVTable ipvlan_vtable;
+extern const NetDevVTable ipvtap_vtable;
 
 const char *ipvlan_mode_to_string(IPVlanMode d) _const_;
 IPVlanMode ipvlan_mode_from_string(const char *d) _pure_;
index 2a74d89e5d229a4159a56bc3b5bed774cc0f3f3f..6ac23052bb3ce94ed37a6ba4852ac62869d63468 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/l2tp.h>
 #include <linux/genetlink.h>
 
index a97c924c5d236e240f6f691585f5d88d9fe9116d..d314b9870344d278e1510841885d7ef5a1b3c919 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/l2tp.h>
 
 #include "in-addr-util.h"
index ccc37cded4684494603a2b8587e698558e1ed1fc..c82a6fd0ac16a4580eb517ddf99c5919da0a91c3 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/if_ether.h>
 #include <linux/if_macsec.h>
 #include <linux/genetlink.h>
index 2bd08ac500950c744a8b0619c494317b888119d6..2a3443a6d4e6dcba45ee7926d5546194d3331095 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <netinet/in.h>
 #include <linux/if_macsec.h>
 
 #include "in-addr-util.h"
index e2c994e9717d48fa2ba4864380219ed55fa0138d..6a6d9dc7520bcad9779c8dfcd1e8d50e8a841d16 100644 (file)
@@ -54,6 +54,8 @@ MACVLAN.Mode,                             config_parse_macvlan_mode,
 MACVTAP.Mode,                             config_parse_macvlan_mode,                 0,                             offsetof(MacVlan, mode)
 IPVLAN.Mode,                              config_parse_ipvlan_mode,                  0,                             offsetof(IPVlan, mode)
 IPVLAN.Flags,                             config_parse_ipvlan_flags,                 0,                             offsetof(IPVlan, flags)
+IPVTAP.Mode,                              config_parse_ipvlan_mode,                  0,                             offsetof(IPVlan, mode)
+IPVTAP.Flags,                             config_parse_ipvlan_flags,                 0,                             offsetof(IPVlan, flags)
 Tunnel.Local,                             config_parse_tunnel_address,               0,                             offsetof(Tunnel, local)
 Tunnel.Remote,                            config_parse_tunnel_address,               0,                             offsetof(Tunnel, remote)
 Tunnel.TOS,                               config_parse_unsigned,                     0,                             offsetof(Tunnel, tos)
@@ -79,6 +81,9 @@ Tunnel.ISATAP,                            config_parse_tristate,
 FooOverUDP.Protocol,                      config_parse_ip_protocol,                  0,                             offsetof(FouTunnel, fou_protocol)
 FooOverUDP.Encapsulation,                 config_parse_fou_encap_type,               0,                             offsetof(FouTunnel, fou_encap_type)
 FooOverUDP.Port,                          config_parse_ip_port,                      0,                             offsetof(FouTunnel, port)
+FooOverUDP.PeerPort,                      config_parse_ip_port,                      0,                             offsetof(FouTunnel, peer_port)
+FooOverUDP.Local,                         config_parse_fou_tunnel_address,           0,                             offsetof(FouTunnel, local)
+FooOverUDP.Peer,                          config_parse_fou_tunnel_address,           0,                             offsetof(FouTunnel, peer)
 L2TP.TunnelId,                            config_parse_l2tp_tunnel_id,               0,                             offsetof(L2tpTunnel, tunnel_id)
 L2TP.PeerTunnelId,                        config_parse_l2tp_tunnel_id,               0,                             offsetof(L2tpTunnel, peer_tunnel_id)
 L2TP.UDPSourcePort,                       config_parse_ip_port,                      0,                             offsetof(L2tpTunnel, l2tp_udp_sport)
@@ -102,7 +107,7 @@ VXLAN.Group,                              config_parse_vxlan_address,
 VXLAN.Local,                              config_parse_vxlan_address,                0,                             offsetof(VxLan, local)
 VXLAN.Remote,                             config_parse_vxlan_address,                0,                             offsetof(VxLan, remote)
 VXLAN.TOS,                                config_parse_unsigned,                     0,                             offsetof(VxLan, tos)
-VXLAN.TTL,                                config_parse_unsigned,                     0,                             offsetof(VxLan, ttl)
+VXLAN.TTL,                                config_parse_vxlan_ttl,                    0,                             offsetof(VxLan, ttl)
 VXLAN.MacLearning,                        config_parse_bool,                         0,                             offsetof(VxLan, learning)
 VXLAN.ARPProxy,                           config_parse_bool,                         0,                             offsetof(VxLan, arp_proxy)
 VXLAN.ReduceARPProxy,                     config_parse_bool,                         0,                             offsetof(VxLan, arp_proxy)
@@ -128,13 +133,14 @@ VXLAN.IPDoNotFragment,                    config_parse_df,
 GENEVE.Id,                                config_parse_geneve_vni,                   0,                             offsetof(Geneve, id)
 GENEVE.Remote,                            config_parse_geneve_address,               0,                             offsetof(Geneve, remote)
 GENEVE.TOS,                               config_parse_uint8,                        0,                             offsetof(Geneve, tos)
-GENEVE.TTL,                               config_parse_uint8,                        0,                             offsetof(Geneve, ttl)
+GENEVE.TTL,                               config_parse_geneve_ttl,                   0,                             offsetof(Geneve, ttl)
 GENEVE.UDPChecksum,                       config_parse_bool,                         0,                             offsetof(Geneve, udpcsum)
 GENEVE.UDP6ZeroCheckSumRx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumrx)
 GENEVE.UDP6ZeroChecksumRx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumrx)
 GENEVE.UDP6ZeroCheckSumTx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumtx)
 GENEVE.UDP6ZeroChecksumTx,                config_parse_bool,                         0,                             offsetof(Geneve, udp6zerocsumtx)
 GENEVE.DestinationPort,                   config_parse_ip_port,                      0,                             offsetof(Geneve, dest_port)
+GENEVE.IPDoNotFragment,                   config_parse_geneve_df,                    0,                             offsetof(Geneve, geneve_df)
 GENEVE.FlowLabel,                         config_parse_geneve_flow_label,            0,                             0
 MACsec.Port,                              config_parse_macsec_port,                  0,                             0
 MACsec.Encrypt,                           config_parse_tristate,                     0,                             offsetof(MACsec, encrypt)
index d8b8bca7e83d2fb7a136128220a4925f732c9ab8..3968ab54956c7e8c0d6d2cae499e6a777d4ee67d 100644 (file)
@@ -45,6 +45,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
         [NETDEV_KIND_MACVTAP] = &macvtap_vtable,
         [NETDEV_KIND_IPVLAN] = &ipvlan_vtable,
+        [NETDEV_KIND_IPVTAP] = &ipvtap_vtable,
         [NETDEV_KIND_VXLAN] = &vxlan_vtable,
         [NETDEV_KIND_IPIP] = &ipip_vtable,
         [NETDEV_KIND_GRE] = &gre_vtable,
@@ -78,6 +79,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_MACVLAN] = "macvlan",
         [NETDEV_KIND_MACVTAP] = "macvtap",
         [NETDEV_KIND_IPVLAN] = "ipvlan",
+        [NETDEV_KIND_IPVTAP] = "ipvtap",
         [NETDEV_KIND_VXLAN] = "vxlan",
         [NETDEV_KIND_IPIP] = "ipip",
         [NETDEV_KIND_GRE] = "gre",
@@ -254,7 +256,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, link_netlink_message
 
         if (link->flags & IFF_UP && netdev->kind == NETDEV_KIND_BOND) {
                 log_netdev_debug(netdev, "Link '%s' was up when attempting to enslave it. Bringing link down.", link->ifname);
-                r = link_down(link);
+                r = link_down(link, NULL);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not bring link down: %m");
         }
@@ -732,7 +734,7 @@ int netdev_load_one(Manager *manager, const char *filename) {
         if (!netdev->filename)
                 return log_oom();
 
-        if (!netdev->mac && netdev->kind != NETDEV_KIND_VLAN) {
+        if (!netdev->mac && !IN_SET(netdev->kind, NETDEV_KIND_VLAN, NETDEV_KIND_BRIDGE)) {
                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r,
index 29ecead029b8bca71e509a8857869a01a6dbefab..dcf072ce94452ef34cc02e40cf6549e6a6ad3ef7 100644 (file)
@@ -24,6 +24,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_MACVLAN,
         NETDEV_KIND_MACVTAP,
         NETDEV_KIND_IPVLAN,
+        NETDEV_KIND_IPVTAP,
         NETDEV_KIND_VXLAN,
         NETDEV_KIND_IPIP,
         NETDEV_KIND_GRE,
index 84f6af8578fc4628d089a73e0c1476bb3990a746..e69a009c315a2deb1d097111885b5d963177ceae 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <linux/fou.h>
 #include <linux/ip.h>
 #include <linux/if_tunnel.h>
index 951138d257a37bdd70c7b47b12b6dd33e13bd7d2..d08acf0c664d740cd006f20cac35f2d57baa5426 100644 (file)
@@ -2,12 +2,12 @@
 
 #include <errno.h>
 #include <fcntl.h>
-#include <linux/if_tun.h>
 #include <net/if.h>
 #include <netinet/if_ether.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <linux/if_tun.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
index 6f62686d0801e8491f9d5056eee38a4dfa55b89e..671b5cb6390a2dadfea2ef2a6a637557b6b06b30 100644 (file)
@@ -3,6 +3,7 @@
 
 typedef struct VCan VCan;
 
+#include <netinet/in.h>
 #include <linux/can/netlink.h>
 
 #include "netdev/netdev.h"
index 3ad95ade0f2be6fbfaa48d28ed78ce8deaa134e3..a0a0b8e39ec4599a4f772c6736c874f2f0cb59b0 100644 (file)
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
-#include <linux/veth.h>
 #include <net/if.h>
+#include <linux/veth.h>
 
 #include "sd-netlink.h"
 
index dd548b338aebc5eebeea7fb268867768b1498172..4d939ab0456adeeba34cc723be728b75d7e9c924 100644 (file)
@@ -1,8 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
 #include <errno.h>
-#include <linux/if_vlan.h>
 #include <net/if.h>
+#include <linux/if_vlan.h>
 
 #include "netdev/vlan.h"
 #include "vlan-util.h"
index 126f6138a366c2ae3c3b471bf1f909c292dbb6fd..e24537083b64fbecc18e10835906214020236bc7 100644 (file)
@@ -65,7 +65,11 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m");
 
-        if (v->ttl != 0) {
+        if (v->inherit) {
+                r = sd_netlink_message_append_flag(m, IFLA_VXLAN_TTL_INHERIT);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL_INHERIT attribute: %m");
+        } else {
                 r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl);
                 if (r < 0)
                         return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m");
@@ -288,6 +292,47 @@ int config_parse_flow_label(const char *unit,
         return 0;
 }
 
+int config_parse_vxlan_ttl(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) {
+        VxLan *v = userdata;
+        unsigned f;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(rvalue, "inherit"))
+                v->inherit = true;
+        else {
+                r = safe_atou(rvalue, &f);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse VXLAN TTL '%s', ignoring assignment: %m", rvalue);
+                        return 0;
+                }
+
+                if (f > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid VXLAN TTL '%s'. TTL must be <= 255. Ignoring assignment.", rvalue);
+                        return 0;
+                }
+
+                v->ttl = f;
+        }
+
+        return 0;
+}
+
 static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
         VxLan *v = VXLAN(netdev);
 
index d448e3ccfe288b2945d5a054ff2e9e826b283d14..0c61bba2b89de3b3753a80f0a46ce2df1baf7a77 100644 (file)
@@ -55,6 +55,7 @@ struct VxLan {
         bool remote_csum_rx;
         bool group_policy;
         bool generic_protocol_extension;
+        bool inherit;
 
         struct ifla_vxlan_port_range port_range;
 };
@@ -69,3 +70,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_port_range);
 CONFIG_PARSER_PROTOTYPE(config_parse_flow_label);
 CONFIG_PARSER_PROTOTYPE(config_parse_df);
+CONFIG_PARSER_PROTOTYPE(config_parse_vxlan_ttl);
index 5ebc5dfed84bffe52e496d6c1380d06cf6919b15..91fcee1401b0056d7c01cb30ae300f57c309a243 100644 (file)
@@ -401,7 +401,7 @@ static void resolve_endpoints(NetDev *netdev) {
         WireguardPeer *peer;
         Wireguard *w;
         Iterator i;
-        int r = 0;
+        int r;
 
         assert(netdev);
         w = WIREGUARD(netdev);
index 862f2a99c4c7b3f4cd74f9a20c9aecc246aab814..ce336c985acdc6b6185fc8f42b96dd5dacc799aa 100644 (file)
@@ -2,6 +2,7 @@
 
 typedef struct Wireguard Wireguard;
 
+#include <netinet/in.h>
 #include <linux/wireguard.h>
 
 #include "in-addr-util.h"
diff --git a/src/network/networkd-can.c b/src/network/networkd-can.c
new file mode 100644 (file)
index 0000000..2df0e88
--- /dev/null
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <net/if.h>
+#include <linux/can/netlink.h>
+
+#include "netlink-util.h"
+#include "networkd-can.h"
+#include "networkd-link.h"
+#include "networkd-manager.h"
+#include "string-util.h"
+
+static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0)
+                /* we warn but don't fail the link, as it may be brought up later */
+                log_link_warning_errno(link, r, "Could not bring up interface: %m");
+
+        return 1;
+}
+
+static int link_up_can(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+        int r;
+
+        assert(link);
+
+        log_link_debug(link, "Bringing CAN link up");
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+        r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set link flags: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        return 0;
+}
+
+static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        log_link_debug(link, "Set link");
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0 && r != -EEXIST) {
+                log_link_error_errno(link, r, "Failed to configure CAN link: %m");
+                link_enter_failed(link);
+        }
+
+        return 1;
+}
+
+static int link_set_can(Link *link) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(link->manager);
+        assert(link->manager->rtnl);
+
+        log_link_debug(link, "Configuring CAN link.");
+
+        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
+
+        r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
+
+        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to open netlink container: %m");
+
+        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
+
+        if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
+                struct can_bittiming bt = {
+                        .bitrate = link->network->can_bitrate,
+                        .sample_point = link->network->can_sample_point,
+                };
+
+                if (link->network->can_bitrate > UINT32_MAX) {
+                        log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
+                        return -ERANGE;
+                }
+
+                log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
+                if (link->network->can_sample_point > 0)
+                        log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
+                else
+                        log_link_debug(link, "Using default sample point");
+
+                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
+        }
+
+        if (link->network->can_restart_us > 0) {
+                char time_string[FORMAT_TIMESPAN_MAX];
+                uint64_t restart_ms;
+
+                if (link->network->can_restart_us == USEC_INFINITY)
+                        restart_ms = 0;
+                else
+                        restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
+
+                format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
+
+                if (restart_ms > UINT32_MAX) {
+                        log_link_error(link, "restart timeout (%s) too big.", time_string);
+                        return -ERANGE;
+                }
+
+                log_link_debug(link, "Setting restart = %s", time_string);
+
+                r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
+        }
+
+        if (link->network->can_triple_sampling >= 0) {
+                struct can_ctrlmode cm = {
+                        .mask = CAN_CTRLMODE_3_SAMPLES,
+                        .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
+                };
+
+                log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
+
+                r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
+        }
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+        r = sd_netlink_message_close_container(m);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
+
+        r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler,
+                               link_netlink_destroy_callback, link);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+        link_ref(link);
+
+        if (!(link->flags & IFF_UP))
+                return link_up_can(link);
+
+        return 0;
+}
+
+static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
+        int r;
+
+        assert(link);
+
+        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+                return 1;
+
+        r = sd_netlink_message_get_errno(m);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not bring down interface: %m");
+                link_enter_failed(link);
+                return 1;
+        }
+
+        r = link_set_can(link);
+        if (r < 0)
+                link_enter_failed(link);
+
+        return 1;
+}
+
+int link_configure_can(Link *link) {
+        int r;
+
+        if (streq_ptr(link->kind, "can")) {
+                /* The CAN interface must be down to configure bitrate, etc... */
+                if ((link->flags & IFF_UP)) {
+                        r = link_down(link, link_down_handler);
+                        if (r < 0) {
+                                link_enter_failed(link);
+                                return r;
+                        }
+                } else {
+                        r = link_set_can(link);
+                        if (r < 0) {
+                                link_enter_failed(link);
+                                return r;
+                        }
+                }
+
+                return 0;
+        }
+
+        if (!(link->flags & IFF_UP)) {
+                r = link_up_can(link);
+                if (r < 0) {
+                        link_enter_failed(link);
+                        return r;
+                }
+        }
+
+        return 0;
+}
diff --git a/src/network/networkd-can.h b/src/network/networkd-can.h
new file mode 100644 (file)
index 0000000..c744bdf
--- /dev/null
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+typedef struct Link Link;
+
+int link_configure_can(Link *link);
index 01f4e955c85e9b899cf4e4b1c0e45866de9ec3b7..7907988a9bb9937c41f9c4411bee2f4df6c52987 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 
 #include "alloc-util.h"
@@ -261,7 +261,7 @@ static int dhcp_lease_lost(Link *link) {
 
                 r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
                 if (r >= 0 && link->original_mtu != mtu) {
-                        r = link_set_mtu(link, link->original_mtu, true);
+                        r = link_set_mtu(link, link->original_mtu);
                         if (r < 0) {
                                 log_link_warning(link,
                                                  "DHCP error: could not reset MTU");
@@ -454,7 +454,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
 
                 r = sd_dhcp_lease_get_mtu(lease, &mtu);
                 if (r >= 0) {
-                        r = link_set_mtu(link, mtu, true);
+                        r = link_set_mtu(link, mtu);
                         if (r < 0)
                                 log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu);
                 }
@@ -512,16 +512,44 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
         return 0;
 }
 
-static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
+static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
+        sd_dhcp_lease *lease;
+        struct in_addr addr;
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(client);
+
+        r = sd_dhcp_client_get_lease(client, &lease);
+        if (r < 0)
+                return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
+
+        r = sd_dhcp_lease_get_server_identifier(lease, &addr);
+        if (r < 0)
+                return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
+
+        if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+                log_struct(LOG_DEBUG,
+                           LOG_LINK_INTERFACE(link),
+                           LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
+                                            ADDRESS_FMT_VAL(addr)));
+                return true;
+        }
+
+        return false;
+}
+
+static int dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
         Link *link = userdata;
-        int r = 0;
+        int r;
 
         assert(link);
         assert(link->network);
         assert(link->manager);
 
         if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return;
+                return 0;
 
         switch (event) {
                 case SD_DHCP_CLIENT_EVENT_STOP:
@@ -532,26 +560,27 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                                 log_link_debug(link, "DHCP client is stopped. Acquiring IPv4 link-local address");
 
                                 r = sd_ipv4ll_start(link->ipv4ll);
-                                if (r < 0) {
-                                        log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
-                                        return;
-                                }
+                                if (r < 0)
+                                        return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
                         }
 
+                        if (link->network->dhcp_send_release)
+                                (void) sd_dhcp_client_send_release(client);
+
                         _fallthrough_;
                 case SD_DHCP_CLIENT_EVENT_EXPIRED:
                 case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
 
                         if (link->network->dhcp_critical) {
                                 log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
-                                return;
+                                return 0;
                         }
 
                         if (link->dhcp_lease) {
                                 r = dhcp_lease_lost(link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -559,7 +588,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                                 r = dhcp_lease_acquired(client, link);
                                 if (r < 0) {
                                         link_enter_failed(link);
-                                        return;
+                                        return r;
                                 }
                         }
 
@@ -568,16 +597,23 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         r = dhcp_lease_renew(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
                 case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
                         r = dhcp_lease_acquired(client, link);
                         if (r < 0) {
                                 link_enter_failed(link);
-                                return;
+                                return r;
                         }
                         break;
+                case SD_DHCP_CLIENT_EVENT_SELECTING:
+                        r = dhcp_server_is_black_listed(link, client);
+                        if (r < 0)
+                                return r;
+                        if (r != 0)
+                                return -ENOMSG;
+                        break;
                 default:
                         if (event < 0)
                                 log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
@@ -586,7 +622,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
                         break;
         }
 
-        return;
+        return 0;
 }
 
 static int dhcp4_set_hostname(Link *link) {
index 7db59d3acad6176deff08ece300aa23357797d8e..afa3e2cfd68a883d06aa0247825585c337ee4f92 100644 (file)
@@ -3,7 +3,7 @@
   Copyright Â© 2014 Intel Corporation. All rights reserved.
 ***/
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 #include "sd-radv.h"
 
@@ -418,7 +418,7 @@ static int dhcp6_address_change(
                 uint32_t lifetime_valid) {
 
         _cleanup_(address_freep) Address *addr = NULL;
-        char buffer[INET6_ADDRSTRLEN];
+        _cleanup_free_ char *buffer = NULL;
         int r;
 
         r = address_new(&addr);
@@ -426,7 +426,7 @@ static int dhcp6_address_change(
                 return r;
 
         addr->family = AF_INET6;
-        memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr));
+        addr->in_addr.in6 = *ip6_addr;
 
         addr->flags = IFA_F_NOPREFIXROUTE;
         addr->prefixlen = 128;
@@ -434,10 +434,10 @@ static int dhcp6_address_change(
         addr->cinfo.ifa_prefered = lifetime_preferred;
         addr->cinfo.ifa_valid = lifetime_valid;
 
+        (void) in_addr_to_string(addr->family, &addr->in_addr, &buffer);
         log_link_info(link,
                       "DHCPv6 address %s/%d timeout preferred %d valid %d",
-                      inet_ntop(AF_INET6, &addr->in_addr.in6, buffer, sizeof(buffer)),
-                      addr->prefixlen, lifetime_preferred, lifetime_valid);
+                      strnull(buffer), addr->prefixlen, lifetime_preferred, lifetime_valid);
 
         r = address_configure(addr, link, dhcp6_address_handler, true);
         if (r < 0)
index fdac574d74fce76abbb247f49776b35610ed51ce..4ae511fc7aeb3f9a3f4bfe5148d0af5d69f1c512 100644 (file)
 #include "networkd-manager.h"
 #include "parse-util.h"
 #include "string-util.h"
+#include "string-table.h"
 #include "util.h"
 #include "vlan-util.h"
 
 #define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
 
+static const char* const fdb_ntf_flags_table[_NEIGHBOR_CACHE_ENTRY_FLAGS_MAX] = {
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_USE] = "use",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_SELF] = "self",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER] = "master",
+        [NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER] = "router",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(fdb_ntf_flags, NeighborCacheEntryFlags);
+
 /* create a new FDB entry or get an existing one. */
 static int fdb_entry_new_static(
                 Network *network,
@@ -68,6 +78,7 @@ static int fdb_entry_new_static(
                 .network = network,
                 .mac_addr = TAKE_PTR(mac_addr),
                 .vni = VXLAN_VID_MAX + 1,
+                .fdb_ntf_flags = NEIGHBOR_CACHE_ENTRY_FLAGS_SELF,
         };
 
         LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
@@ -106,9 +117,6 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
 /* send a request to the kernel to add a FDB entry in its static MAC table. */
 int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        sd_netlink *rtnl;
-        Bridge *bridge;
-        uint8_t flags;
         int r;
 
         assert(link);
@@ -116,20 +124,12 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
         assert(link->manager);
         assert(fdb_entry);
 
-        rtnl = link->manager->rtnl;
-        bridge = BRIDGE(link->network->bridge);
-
         /* create new RTM message */
-        r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
+        r = sd_rtnl_message_new_neigh(link->manager->rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
         if (r < 0)
                 return rtnl_log_create_error(r);
 
-        if (bridge)
-                flags = NTF_MASTER;
-        else
-                flags = NTF_SELF;
-
-        r = sd_rtnl_message_neigh_set_flags(req, flags);
+        r = sd_rtnl_message_neigh_set_flags(req, fdb_entry->fdb_ntf_flags);
         if (r < 0)
                 return rtnl_log_create_error(r);
 
@@ -162,7 +162,7 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
         }
 
         /* send message to the kernel to update its internal static MAC table. */
-        r = netlink_call_async(rtnl, NULL, req, set_fdb_handler,
+        r = netlink_call_async(link->manager->rtnl, NULL, req, set_fdb_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@@ -359,3 +359,45 @@ int config_parse_fdb_vxlan_vni(
 
         return 0;
 }
+
+
+int config_parse_fdb_ntf_flags(
+                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_(fdb_entry_free_or_set_invalidp) FdbEntry *fdb_entry = NULL;
+        Network *network = userdata;
+        NeighborCacheEntryFlags f;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = fdb_entry_new_static(network, filename, section_line, &fdb_entry);
+        if (r < 0)
+                return log_oom();
+
+        f = fdb_ntf_flags_from_string(rvalue);
+        if (f < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, 0,
+                           "FDB failed to parse AssociatedWith=, ignoring assignment: %s",
+                           rvalue);
+                return 0;
+        }
+
+        fdb_entry->fdb_ntf_flags = f;
+        fdb_entry = NULL;
+
+        return 0;
+}
index 6954e555fa413186d4cfc24b1244e3a280e6c252..bcdd8ce3cb241ab21ed262352c5e31f002c4d9a3 100644 (file)
@@ -5,6 +5,8 @@
   Copyright Â© 2014 Intel Corporation. All rights reserved.
 ***/
 
+#include <linux/neighbour.h>
+
 #include "conf-parser.h"
 #include "list.h"
 #include "macro.h"
@@ -15,6 +17,15 @@ typedef struct FdbEntry FdbEntry;
 typedef struct Link Link;
 typedef struct NetworkConfigSection NetworkConfigSection;
 
+typedef enum NeighborCacheEntryFlags {
+        NEIGHBOR_CACHE_ENTRY_FLAGS_USE = NTF_USE,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_SELF = NTF_SELF,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_MASTER = NTF_MASTER,
+        NEIGHBOR_CACHE_ENTRY_FLAGS_ROUTER = NTF_ROUTER,
+        _NEIGHBOR_CACHE_ENTRY_FLAGS_MAX,
+        _NEIGHBOR_CACHE_ENTRY_FLAGS_INVALID = -1,
+} NeighborCacheEntryFlags;
+
 struct FdbEntry {
         Network *network;
         NetworkConfigSection *section;
@@ -26,6 +37,7 @@ struct FdbEntry {
 
         struct ether_addr *mac_addr;
         union in_addr_union destination_addr;
+        NeighborCacheEntryFlags fdb_ntf_flags;
 
         LIST_FIELDS(FdbEntry, static_fdb_entries);
 };
@@ -35,7 +47,11 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
 
 DEFINE_NETWORK_SECTION_FUNCTIONS(FdbEntry, fdb_entry_free);
 
+const char* fdb_ntf_flags_to_string(NeighborCacheEntryFlags i) _const_;
+NeighborCacheEntryFlags fdb_ntf_flags_from_string(const char *s) _pure_;
+
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_hwaddr);
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vlan_id);
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_destination);
 CONFIG_PARSER_PROTOTYPE(config_parse_fdb_vxlan_vni);
+CONFIG_PARSER_PROTOTYPE(config_parse_fdb_ntf_flags);
index 79e90f2f5af640b254857688144efd2cf92f8888..9df5646a7e61c0186375383f7b42c8ea4ee2334d 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 
 #include "network-internal.h"
@@ -34,7 +34,9 @@ static int ipv4ll_address_lost(Link *link) {
         address->prefixlen = 16;
         address->scope = RT_SCOPE_LINK;
 
-        address_remove(address, link, NULL);
+        r = address_remove(address, link, NULL);
+        if (r < 0)
+                return r;
 
         r = route_new(&route);
         if (r < 0)
@@ -44,7 +46,9 @@ static int ipv4ll_address_lost(Link *link) {
         route->scope = RT_SCOPE_LINK;
         route->priority = IPV4LL_ROUTE_METRIC;
 
-        route_remove(route, link, NULL);
+        r = route_remove(route, link, NULL);
+        if (r < 0)
+                return r;
 
         link_check_ready(link);
 
index e2d77e9ad2c56f24892733d66929004a20caad11..863171b0712ffcff041de28f629dc3e51b8625ad 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
 #include <unistd.h>
 
index 4db9f3f980ff4d46a025956f1ccb091dcf3c4cb1..ac123ddc1ebe9fc34499e6bc51fc7fc1b33460c1 100644 (file)
@@ -1,8 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
-#include <netinet/ether.h>
+#include <netinet/in.h>
 #include <linux/if.h>
-#include <linux/can/netlink.h>
 #include <unistd.h>
 
 #include "alloc-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "missing_network.h"
+#include "netdev/bond.h"
+#include "netdev/bridge.h"
 #include "netdev/vrf.h"
 #include "netlink-util.h"
 #include "network-internal.h"
+#include "networkd-can.h"
 #include "networkd-ipv6-proxy-ndp.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
@@ -119,7 +121,7 @@ bool link_ipv4ll_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6"))
                 return false;
 
         if (link->network->bond)
@@ -137,7 +139,7 @@ bool link_ipv4ll_fallback_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "ip6gre", "ip6tnl", "sit", "vti", "vti6"))
                 return false;
 
         if (link->network->bond)
@@ -158,7 +160,7 @@ static bool link_ipv6ll_enabled(Link *link) {
         if (!link->network)
                 return false;
 
-        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard"))
+        if (STRPTR_IN_SET(link->kind, "vrf", "wireguard", "ipip", "gre", "sit", "vti"))
                 return false;
 
         if (link->network->bond)
@@ -195,42 +197,6 @@ static bool link_radv_enabled(Link *link) {
         return link->network->router_prefix_delegation != RADV_PREFIX_DELEGATION_NONE;
 }
 
-static bool link_lldp_rx_enabled(Link *link) {
-        assert(link);
-
-        if (link->flags & IFF_LOOPBACK)
-                return false;
-
-        if (link->iftype != ARPHRD_ETHER)
-                return false;
-
-        if (!link->network)
-                return false;
-
-        /* LLDP should be handled on bridge slaves as those have a direct
-         * connection to their peers not on the bridge master. Linux doesn't
-         * even (by default) forward lldp packets to the bridge master.*/
-        if (streq_ptr("bridge", link->kind))
-                return false;
-
-        return link->network->lldp_mode != LLDP_MODE_NO;
-}
-
-static bool link_lldp_emit_enabled(Link *link) {
-        assert(link);
-
-        if (link->flags & IFF_LOOPBACK)
-                return false;
-
-        if (link->iftype != ARPHRD_ETHER)
-                return false;
-
-        if (!link->network)
-                return false;
-
-        return link->network->lldp_emit != LLDP_EMIT_NO;
-}
-
 static bool link_ipv4_forward_enabled(Link *link) {
         assert(link);
 
@@ -983,6 +949,7 @@ void link_check_ready(Link *link) {
         if (!link->addresses_ready) {
                 link->addresses_ready = true;
                 link_request_set_routes(link);
+                return;
         }
 
         if (!link->static_routes_configured)
@@ -1136,20 +1103,20 @@ static int link_push_uplink_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
         log_debug("Copying NTP server information from %s", link->ifname);
 
         STRV_FOREACH(a, link->network->ntp) {
-                struct in_addr ia;
+                union in_addr_union ia;
 
                 /* Only look for IPv4 addresses */
-                if (inet_pton(AF_INET, *a, &ia) <= 0)
+                if (in_addr_from_string(AF_INET, *a, &ia) <= 0)
                         continue;
 
                 /* Never propagate obviously borked data */
-                if (in4_addr_is_null(&ia) || in4_addr_is_localhost(&ia))
+                if (in4_addr_is_null(&ia.in) || in4_addr_is_localhost(&ia.in))
                         continue;
 
                 if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1))
                         return log_oom();
 
-                addresses[n_addresses++] = ia;
+                addresses[n_addresses++] = ia.in;
         }
 
         if (link->network->dhcp_use_ntp && link->dhcp_lease) {
@@ -1367,7 +1334,7 @@ static int link_request_set_addresses(Link *link) {
 }
 
 static int link_set_bridge_vlan(Link *link) {
-        int r = 0;
+        int r;
 
         r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
         if (r < 0)
@@ -1389,22 +1356,6 @@ static int link_set_proxy_arp(Link *link) {
         return 0;
 }
 
-static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Set link");
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0 && r != -EEXIST) {
-                log_link_error_errno(link, r, "Could not join netdev: %m");
-                link_enter_failed(link);
-        }
-
-        return 1;
-}
-
 static int link_configure_after_setting_mtu(Link *link);
 
 static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@@ -1433,7 +1384,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
         return 1;
 }
 
-int link_set_mtu(Link *link, uint32_t mtu, bool force) {
+int link_set_mtu(Link *link, uint32_t mtu) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -1444,7 +1395,7 @@ int link_set_mtu(Link *link, uint32_t mtu, bool force) {
         if (mtu == 0 || link->setting_mtu)
                 return 0;
 
-        if (force ? link->mtu == mtu : link->mtu >= mtu)
+        if (link->mtu == mtu)
                 return 0;
 
         log_link_debug(link, "Setting MTU: %" PRIu32, mtu);
@@ -1482,6 +1433,48 @@ int link_set_mtu(Link *link, uint32_t mtu, bool force) {
         return 0;
 }
 
+static bool link_reduces_vlan_mtu(Link *link) {
+        /* See netif_reduces_vlan_mtu() in kernel. */
+        return streq_ptr(link->kind, "macsec");
+}
+
+static uint32_t link_get_requested_mtu_by_stacked_netdevs(Link *link) {
+        uint32_t mtu = 0;
+        NetDev *dev;
+        Iterator i;
+
+        HASHMAP_FOREACH(dev, link->network->stacked_netdevs, i)
+                if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
+                        /* See vlan_dev_change_mtu() in kernel. */
+                        mtu = MAX(mtu, link_reduces_vlan_mtu(link) ? dev->mtu + 4 : dev->mtu);
+
+                else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
+                        /* See macvlan_change_mtu() in kernel. */
+                        mtu = dev->mtu;
+
+        return mtu;
+}
+
+static int link_configure_mtu(Link *link) {
+        uint32_t mtu;
+
+        assert(link);
+        assert(link->network);
+
+        if (link->network->mtu > 0)
+                return link_set_mtu(link, link->network->mtu);
+
+        mtu = link_get_requested_mtu_by_stacked_netdevs(link);
+        if (link->mtu >= mtu)
+                return 0;
+
+        log_link_notice(link, "Bumping MTU bytes from %"PRIu32" to %"PRIu32" because of stacked device. "
+                        "If it is not desired, then please explicitly specify MTUBytes= setting.",
+                        link->mtu, mtu);
+
+        return link_set_mtu(link, mtu);
+}
+
 static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -1551,268 +1544,6 @@ static int link_set_flags(Link *link) {
         return 0;
 }
 
-static int link_set_bridge(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set message family: %m");
-
-        r = sd_netlink_message_open_container(req, IFLA_PROTINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
-
-        if (link->network->use_bpdu >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, link->network->use_bpdu);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
-        }
-
-        if (link->network->hairpin >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
-        }
-
-        if (link->network->fast_leave >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
-        }
-
-        if (link->network->allow_port_to_be_root >=  0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
-
-        }
-
-        if (link->network->unicast_flood >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
-        }
-
-        if (link->network->multicast_flood >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_FLOOD, link->network->multicast_flood);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_FLOOD attribute: %m");
-        }
-
-        if (link->network->multicast_to_unicast >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MCAST_TO_UCAST, link->network->multicast_to_unicast);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MCAST_TO_UCAST attribute: %m");
-        }
-
-        if (link->network->neighbor_suppression >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_NEIGH_SUPPRESS, link->network->neighbor_suppression);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_NEIGH_SUPPRESS attribute: %m");
-        }
-
-        if (link->network->learning >= 0) {
-                r = sd_netlink_message_append_u8(req, IFLA_BRPORT_LEARNING, link->network->learning);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_LEARNING attribute: %m");
-        }
-
-        if (link->network->cost != 0) {
-                r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m");
-        }
-
-        if (link->network->priority != LINK_BRIDGE_PORT_PRIORITY_INVALID) {
-                r = sd_netlink_message_append_u16(req, IFLA_BRPORT_PRIORITY, link->network->priority);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PRIORITY attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return r;
-}
-
-static int link_set_bond_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
-        int r;
-
-        assert(m);
-        assert(link);
-        assert(link->ifname);
-
-        if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
-                return 1;
-
-        r = sd_netlink_message_get_errno(m);
-        if (r < 0) {
-                log_link_warning_errno(link, r, "Could not set bonding interface: %m");
-                return 1;
-        }
-
-        return 1;
-}
-
-static int link_set_bond(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_NEWLINK, link->network->bond->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
-
-        r = sd_netlink_message_open_container(req, IFLA_LINKINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
-
-        r = sd_netlink_message_open_container_union(req, IFLA_INFO_DATA, "bond");
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        if (link->network->active_slave) {
-                r = sd_netlink_message_append_u32(req, IFLA_BOND_ACTIVE_SLAVE, link->ifindex);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_ACTIVE_SLAVE attribute: %m");
-        }
-
-        if (link->network->primary_slave) {
-                r = sd_netlink_message_append_u32(req, IFLA_BOND_PRIMARY, link->ifindex);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_BOND_PRIMARY attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m");
-
-        r = sd_netlink_message_close_container(req);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r,  "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return r;
-}
-
-static int link_lldp_save(Link *link) {
-        _cleanup_free_ char *temp_path = NULL;
-        _cleanup_fclose_ FILE *f = NULL;
-        sd_lldp_neighbor **l = NULL;
-        int n = 0, r, i;
-
-        assert(link);
-        assert(link->lldp_file);
-
-        if (!link->lldp) {
-                (void) unlink(link->lldp_file);
-                return 0;
-        }
-
-        r = sd_lldp_get_neighbors(link->lldp, &l);
-        if (r < 0)
-                goto finish;
-        if (r == 0) {
-                (void) unlink(link->lldp_file);
-                goto finish;
-        }
-
-        n = r;
-
-        r = fopen_temporary(link->lldp_file, &f, &temp_path);
-        if (r < 0)
-                goto finish;
-
-        fchmod(fileno(f), 0644);
-
-        for (i = 0; i < n; i++) {
-                const void *p;
-                le64_t u;
-                size_t sz;
-
-                r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
-                if (r < 0)
-                        goto finish;
-
-                u = htole64(sz);
-                (void) fwrite(&u, 1, sizeof(u), f);
-                (void) fwrite(p, 1, sz, f);
-        }
-
-        r = fflush_and_check(f);
-        if (r < 0)
-                goto finish;
-
-        if (rename(temp_path, link->lldp_file) < 0) {
-                r = -errno;
-                goto finish;
-        }
-
-finish:
-        if (r < 0) {
-                (void) unlink(link->lldp_file);
-                if (temp_path)
-                        (void) unlink(temp_path);
-
-                log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
-        }
-
-        if (l) {
-                for (i = 0; i < n; i++)
-                        sd_lldp_neighbor_unref(l[i]);
-                free(l);
-        }
-
-        return r;
-}
-
-static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
-        Link *link = userdata;
-        int r;
-
-        assert(link);
-
-        (void) link_lldp_save(link);
-
-        if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
-                /* If we received information about a new neighbor, restart the LLDP "fast" logic */
-
-                log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
-
-                r = link_lldp_emit_start(link);
-                if (r < 0)
-                        log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
-        }
-}
-
 static int link_acquire_ipv6_conf(Link *link) {
         int r;
 
@@ -1906,7 +1637,8 @@ bool link_has_carrier(Link *link) {
 
         if (link->kernel_operstate == IF_OPER_UNKNOWN)
                 /* operstate may not be implemented, so fall back to flags */
-                if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT))
+                if (FLAGS_SET(link->flags, IFF_LOWER_UP | IFF_RUNNING) &&
+                    !FLAGS_SET(link->flags, IFF_DORMANT))
                         return true;
 
         return false;
@@ -1937,6 +1669,9 @@ static int link_configure_addrgen_mode(Link *link) {
         assert(link->manager);
         assert(link->manager->rtnl);
 
+        if (!socket_ipv6_is_supported())
+                return 0;
+
         log_link_debug(link, "Setting address genmode for link");
 
         r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
@@ -2030,72 +1765,6 @@ static int link_up(Link *link) {
                         return log_link_error_errno(link, r, "Could not set MAC address: %m");
         }
 
-        if (link_ipv6_enabled(link)) {
-                uint8_t ipv6ll_mode;
-
-                r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
-
-                /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */
-                r = sd_netlink_message_open_container(req, AF_INET6);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
-
-                if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) {
-                        r = sd_netlink_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6);
-                        if (r < 0)
-                                return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m");
-                }
-
-                if (!link_ipv6ll_enabled(link))
-                        ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
-                else if (sysctl_read_ip_property(AF_INET6, link->ifname, "stable_secret", NULL) < 0)
-                        /* The file may not exist. And event if it exists, when stable_secret is unset,
-                         * reading the file fails with EIO. */
-                        ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
-                else
-                        ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
-
-                r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
-
-                r = sd_netlink_message_close_container(req);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m");
-
-                r = sd_netlink_message_close_container(req);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
-        }
-
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        return 0;
-}
-
-static int link_up_can(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
-        int r;
-
-        assert(link);
-
-        log_link_debug(link, "Bringing CAN link up");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
-
-        r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set link flags: %m");
-
         r = netlink_call_async(link->manager->rtnl, NULL, req, link_up_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
@@ -2106,119 +1775,6 @@ static int link_up_can(Link *link) {
         return 0;
 }
 
-static int link_set_can(Link *link) {
-        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->manager);
-        assert(link->manager->rtnl);
-
-        log_link_debug(link, "link_set_can");
-
-        r = sd_rtnl_message_new_link(link->manager->rtnl, &m, RTM_NEWLINK, link->ifindex);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to allocate netlink message: %m");
-
-        r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not set netlink flags: %m");
-
-        r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to open netlink container: %m");
-
-        r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not append IFLA_INFO_DATA attribute: %m");
-
-        if (link->network->can_bitrate > 0 || link->network->can_sample_point > 0) {
-                struct can_bittiming bt = {
-                        .bitrate = link->network->can_bitrate,
-                        .sample_point = link->network->can_sample_point,
-                };
-
-                if (link->network->can_bitrate > UINT32_MAX) {
-                        log_link_error(link, "bitrate (%zu) too big.", link->network->can_bitrate);
-                        return -ERANGE;
-                }
-
-                log_link_debug(link, "Setting bitrate = %d bit/s", bt.bitrate);
-                if (link->network->can_sample_point > 0)
-                        log_link_debug(link, "Setting sample point = %d.%d%%", bt.sample_point / 10, bt.sample_point % 10);
-                else
-                        log_link_debug(link, "Using default sample point");
-
-                r = sd_netlink_message_append_data(m, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_BITTIMING attribute: %m");
-        }
-
-        if (link->network->can_restart_us > 0) {
-                char time_string[FORMAT_TIMESPAN_MAX];
-                uint64_t restart_ms;
-
-                if (link->network->can_restart_us == USEC_INFINITY)
-                        restart_ms = 0;
-                else
-                        restart_ms = DIV_ROUND_UP(link->network->can_restart_us, USEC_PER_MSEC);
-
-                format_timespan(time_string, FORMAT_TIMESPAN_MAX, restart_ms * 1000, MSEC_PER_SEC);
-
-                if (restart_ms > UINT32_MAX) {
-                        log_link_error(link, "restart timeout (%s) too big.", time_string);
-                        return -ERANGE;
-                }
-
-                log_link_debug(link, "Setting restart = %s", time_string);
-
-                r = sd_netlink_message_append_u32(m, IFLA_CAN_RESTART_MS, restart_ms);
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_RESTART_MS attribute: %m");
-        }
-
-        if (link->network->can_triple_sampling >= 0) {
-                struct can_ctrlmode cm = {
-                        .mask = CAN_CTRLMODE_3_SAMPLES,
-                        .flags = link->network->can_triple_sampling ? CAN_CTRLMODE_3_SAMPLES : 0,
-                };
-
-                log_link_debug(link, "%sabling triple-sampling", link->network->can_triple_sampling ? "En" : "Dis");
-
-                r = sd_netlink_message_append_data(m, IFLA_CAN_CTRLMODE, &cm, sizeof(cm));
-                if (r < 0)
-                        return log_link_error_errno(link, r, "Could not append IFLA_CAN_CTRLMODE attribute: %m");
-        }
-
-        r = sd_netlink_message_close_container(m);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
-
-        r = sd_netlink_message_close_container(m);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Failed to close netlink container: %m");
-
-        r = netlink_call_async(link->manager->rtnl, NULL, m, link_set_handler,
-                               link_netlink_destroy_callback, link);
-        if (r < 0)
-                return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
-
-        link_ref(link);
-
-        if (!(link->flags & IFF_UP)) {
-                r = link_up_can(link);
-                if (r < 0) {
-                        link_enter_failed(link);
-                        return r;
-                }
-        }
-
-        log_link_debug(link, "link_set_can done");
-
-        return r;
-}
-
 static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
         int r;
 
@@ -2231,13 +1787,10 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link
         if (r < 0)
                 log_link_warning_errno(link, r, "Could not bring down interface: %m");
 
-        if (streq_ptr(link->kind, "can"))
-                link_set_can(link);
-
         return 1;
 }
 
-int link_down(Link *link) {
+int link_down(Link *link, link_netlink_message_handler_t callback) {
         _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
         int r;
 
@@ -2256,7 +1809,8 @@ int link_down(Link *link) {
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not set link flags: %m");
 
-        r = netlink_call_async(link->manager->rtnl, NULL, req, link_down_handler,
+        r = netlink_call_async(link->manager->rtnl, NULL, req,
+                               callback ?: link_down_handler,
                                link_netlink_destroy_callback, link);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
@@ -2288,7 +1842,7 @@ static int link_handle_bound_to_list(Link *link) {
                 }
 
         if (!required_up && link_is_up) {
-                r = link_down(link);
+                r = link_down(link, NULL);
                 if (r < 0)
                         return r;
         } else if (required_up && !link_is_up) {
@@ -3015,56 +2569,6 @@ static int link_drop_config(Link *link) {
         return 0;
 }
 
-static int link_update_lldp(Link *link) {
-        int r;
-
-        assert(link);
-
-        if (!link->lldp)
-                return 0;
-
-        if (link->flags & IFF_UP) {
-                r = sd_lldp_start(link->lldp);
-                if (r > 0)
-                        log_link_debug(link, "Started LLDP.");
-        } else {
-                r = sd_lldp_stop(link->lldp);
-                if (r > 0)
-                        log_link_debug(link, "Stopped LLDP.");
-        }
-
-        return r;
-}
-
-static int link_configure_can(Link *link) {
-        int r;
-
-        if (streq_ptr(link->kind, "can")) {
-                /* The CAN interface must be down to configure bitrate, etc... */
-                if ((link->flags & IFF_UP)) {
-                        r = link_down(link);
-                        if (r < 0) {
-                                link_enter_failed(link);
-                                return r;
-                        }
-
-                        return 0;
-                }
-
-                return link_set_can(link);
-        }
-
-        if (!(link->flags & IFF_UP)) {
-                r = link_up_can(link);
-                if (r < 0) {
-                        link_enter_failed(link);
-                        return r;
-                }
-        }
-
-        return 0;
-}
-
 static int link_configure(Link *link) {
         int r;
 
@@ -3169,47 +2673,18 @@ static int link_configure(Link *link) {
         }
 
         if (link_lldp_rx_enabled(link)) {
-                r = sd_lldp_new(&link->lldp);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_match_capabilities(link->lldp,
-                                               link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
-                                               SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
-                                               SD_LLDP_SYSTEM_CAPABILITIES_ALL);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_filter_address(link->lldp, &link->mac);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_attach_event(link->lldp, NULL, 0);
-                if (r < 0)
-                        return r;
-
-                r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
-                if (r < 0)
-                        return r;
-
-                r = link_update_lldp(link);
+                r = link_lldp_rx_configure(link);
                 if (r < 0)
                         return r;
         }
 
-        r = link_set_mtu(link, link->network->mtu, link->network->mtu_is_set);
+        r = link_configure_mtu(link);
         if (r < 0)
                 return r;
 
-        if (socket_ipv6_is_supported()) {
-                r = link_configure_addrgen_mode(link);
-                if (r < 0)
-                        return r;
-        }
+        r = link_configure_addrgen_mode(link);
+        if (r < 0)
+                return r;
 
         return link_configure_after_setting_mtu(link);
 }
@@ -4063,12 +3538,11 @@ int link_save(Link *link) {
                 admin_state, oper_state);
 
         if (link->network) {
-                bool space;
+                char **dhcp6_domains = NULL, **dhcp_domains = NULL;
+                const char *dhcp_domainname = NULL, *p;
                 sd_dhcp6_lease *dhcp6_lease = NULL;
-                const char *dhcp_domainname = NULL;
-                char **dhcp6_domains = NULL;
-                char **dhcp_domains = NULL;
                 unsigned j;
+                bool space;
 
                 fprintf(f, "REQUIRED_FOR_ONLINE=%s\n",
                         yes_no(link->network->required_for_online));
@@ -4185,7 +3659,10 @@ int link_save(Link *link) {
                                 (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
                 }
 
-                ordered_set_print(f, "DOMAINS=", link->network->search_domains);
+                fputs("DOMAINS=", f);
+                space = false;
+                ORDERED_SET_FOREACH(p, link->network->search_domains, i)
+                        fputs_with_space(f, p, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
                         NDiscDNSSL *dd;
@@ -4203,7 +3680,10 @@ int link_save(Link *link) {
 
                 fputc('\n', f);
 
-                ordered_set_print(f, "ROUTE_DOMAINS=", link->network->route_domains);
+                fputs("ROUTE_DOMAINS=", f);
+                space = false;
+                ORDERED_SET_FOREACH(p, link->network->route_domains, i)
+                        fputs_with_space(f, p, NULL, &space);
 
                 if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
                         NDiscDNSSL *dd;
index 930dd25f924d52a5a5d18c0c698da7917f83496d..cc4cd07075509855fb0eab9aa2475c28dcbea2d7 100644 (file)
@@ -139,7 +139,7 @@ int link_get(Manager *m, int ifindex, Link **ret);
 int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
 void link_drop(Link *link);
 
-int link_down(Link *link);
+int link_down(Link *link, link_netlink_message_handler_t callback);
 
 void link_enter_failed(Link *link);
 int link_initialized(Link *link, sd_device *device);
@@ -158,7 +158,7 @@ bool link_has_carrier(Link *link);
 
 int link_ipv6ll_gained(Link *link, const struct in6_addr *address);
 
-int link_set_mtu(Link *link, uint32_t mtu, bool force);
+int link_set_mtu(Link *link, uint32_t mtu);
 
 int ipv4ll_configure(Link *link);
 bool link_ipv4ll_enabled(Link *link);
diff --git a/src/network/networkd-lldp-rx.c b/src/network/networkd-lldp-rx.c
new file mode 100644 (file)
index 0000000..95018d3
--- /dev/null
@@ -0,0 +1,197 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <net/if.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "networkd-link.h"
+#include "networkd-lldp-rx.h"
+#include "networkd-lldp-tx.h"
+#include "networkd-network.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "tmpfile-util.h"
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
+
+static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
+        [LLDP_MODE_NO] = "no",
+        [LLDP_MODE_YES] = "yes",
+        [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
+};
+
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
+
+bool link_lldp_rx_enabled(Link *link) {
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return false;
+
+        if (link->iftype != ARPHRD_ETHER)
+                return false;
+
+        if (!link->network)
+                return false;
+
+        /* LLDP should be handled on bridge slaves as those have a direct
+         * connection to their peers not on the bridge master. Linux doesn't
+         * even (by default) forward lldp packets to the bridge master.*/
+        if (streq_ptr("bridge", link->kind))
+                return false;
+
+        return link->network->lldp_mode != LLDP_MODE_NO;
+}
+
+static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) {
+        Link *link = userdata;
+        int r;
+
+        assert(link);
+
+        (void) link_lldp_save(link);
+
+        if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) {
+                /* If we received information about a new neighbor, restart the LLDP "fast" logic */
+
+                log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission.");
+
+                r = link_lldp_emit_start(link);
+                if (r < 0)
+                        log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m");
+        }
+}
+
+int link_lldp_rx_configure(Link *link) {
+        int r;
+
+        r = sd_lldp_new(&link->lldp);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_match_capabilities(link->lldp,
+                                       link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ?
+                                       SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS :
+                                       SD_LLDP_SYSTEM_CAPABILITIES_ALL);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_filter_address(link->lldp, &link->mac);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_attach_event(link->lldp, NULL, 0);
+        if (r < 0)
+                return r;
+
+        r = sd_lldp_set_callback(link->lldp, lldp_handler, link);
+        if (r < 0)
+                return r;
+
+        r = link_update_lldp(link);
+        if (r < 0)
+                return r;
+
+        return 0;
+}
+
+int link_update_lldp(Link *link) {
+        int r;
+
+        assert(link);
+
+        if (!link->lldp)
+                return 0;
+
+        if (link->flags & IFF_UP) {
+                r = sd_lldp_start(link->lldp);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to start LLDP: %m");
+                if (r > 0)
+                        log_link_debug(link, "Started LLDP.");
+        } else {
+                r = sd_lldp_stop(link->lldp);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to stop LLDP: %m");
+                if (r > 0)
+                        log_link_debug(link, "Stopped LLDP.");
+        }
+
+        return r;
+}
+
+int link_lldp_save(Link *link) {
+        _cleanup_free_ char *temp_path = NULL;
+        _cleanup_fclose_ FILE *f = NULL;
+        sd_lldp_neighbor **l = NULL;
+        int n = 0, r, i;
+
+        assert(link);
+        assert(link->lldp_file);
+
+        if (!link->lldp) {
+                (void) unlink(link->lldp_file);
+                return 0;
+        }
+
+        r = sd_lldp_get_neighbors(link->lldp, &l);
+        if (r < 0)
+                goto finish;
+        if (r == 0) {
+                (void) unlink(link->lldp_file);
+                goto finish;
+        }
+
+        n = r;
+
+        r = fopen_temporary(link->lldp_file, &f, &temp_path);
+        if (r < 0)
+                goto finish;
+
+        fchmod(fileno(f), 0644);
+
+        for (i = 0; i < n; i++) {
+                const void *p;
+                le64_t u;
+                size_t sz;
+
+                r = sd_lldp_neighbor_get_raw(l[i], &p, &sz);
+                if (r < 0)
+                        goto finish;
+
+                u = htole64(sz);
+                (void) fwrite(&u, 1, sizeof(u), f);
+                (void) fwrite(p, 1, sz, f);
+        }
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                goto finish;
+
+        if (rename(temp_path, link->lldp_file) < 0) {
+                r = -errno;
+                goto finish;
+        }
+
+finish:
+        if (r < 0) {
+                (void) unlink(link->lldp_file);
+                if (temp_path)
+                        (void) unlink(temp_path);
+
+                log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file);
+        }
+
+        if (l) {
+                for (i = 0; i < n; i++)
+                        sd_lldp_neighbor_unref(l[i]);
+                free(l);
+        }
+
+        return r;
+}
diff --git a/src/network/networkd-lldp-rx.h b/src/network/networkd-lldp-rx.h
new file mode 100644 (file)
index 0000000..12f512f
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include <stdbool.h>
+
+#include "conf-parser.h"
+
+typedef struct Link Link;
+
+typedef enum LLDPMode {
+        LLDP_MODE_NO = 0,
+        LLDP_MODE_YES = 1,
+        LLDP_MODE_ROUTERS_ONLY = 2,
+        _LLDP_MODE_MAX,
+        _LLDP_MODE_INVALID = -1,
+} LLDPMode;
+
+bool link_lldp_rx_enabled(Link *link);
+int link_lldp_rx_configure(Link *link);
+int link_update_lldp(Link *link);
+int link_lldp_save(Link *link);
+
+const char* lldp_mode_to_string(LLDPMode m) _const_;
+LLDPMode lldp_mode_from_string(const char *s) _pure_;
+
+CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
index 8fd6365e68b42870ba5c719d91dcfce59ccc383c..00c4358a0a89500900de89406815f7fa9913b766 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <endian.h>
 #include <inttypes.h>
+#include <net/if.h>
 #include <string.h>
 
 #include "alloc-util.h"
@@ -9,6 +10,7 @@
 #include "fd-util.h"
 #include "hostname-util.h"
 #include "missing_network.h"
+#include "networkd-link.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-manager.h"
 #include "parse-util.h"
@@ -38,6 +40,21 @@ static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = {
         [LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }},
 };
 
+bool link_lldp_emit_enabled(Link *link) {
+        assert(link);
+
+        if (link->flags & IFF_LOOPBACK)
+                return false;
+
+        if (link->iftype != ARPHRD_ETHER)
+                return false;
+
+        if (!link->network)
+                return false;
+
+        return link->network->lldp_emit != LLDP_EMIT_NO;
+}
+
 static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) {
         assert(p);
 
index 6842804a7e0de7b1e78e13169e20b84ce081c77e..561becda41c84fec4d967165e0fe181009e9c637 100644 (file)
@@ -1,8 +1,11 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include <stdbool.h>
+
 #include "conf-parser.h"
-#include "networkd-link.h"
+
+typedef struct Link Link;
 
 typedef enum LLDPEmit {
         LLDP_EMIT_NO,
@@ -12,6 +15,7 @@ typedef enum LLDPEmit {
         _LLDP_EMIT_MAX,
 } LLDPEmit;
 
+bool link_lldp_emit_enabled(Link *link);
 int link_lldp_emit_start(Link *link);
 void link_lldp_emit_stop(Link *link);
 
index a842d131a53f809861e690a034855234d41a207c..de177e6d1abfa9e80d72a4eed5f519fbc97ec3c1 100644 (file)
@@ -1,9 +1,10 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <netinet/in.h>
 #include <sys/socket.h>
+#include <unistd.h>
 #include <linux/if.h>
 #include <linux/fib_rules.h>
-#include <unistd.h>
 
 #include "sd-daemon.h"
 #include "sd-netlink.h"
@@ -477,19 +478,17 @@ int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, vo
 }
 
 int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
+        _cleanup_free_ char *buf = NULL;
         Manager *m = userdata;
         Link *link = NULL;
         uint16_t type;
-        unsigned char flags;
-        int family;
-        unsigned char prefixlen;
-        unsigned char scope;
+        unsigned char flags, prefixlen, scope;
         union in_addr_union in_addr = IN_ADDR_NULL;
         struct ifa_cacheinfo cinfo;
         Address *address = NULL;
-        char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
+        char valid_buf[FORMAT_TIMESPAN_MAX];
         const char *valid_str = NULL;
-        int r, ifindex;
+        int ifindex, family, r;
 
         assert(rtnl);
         assert(message);
@@ -577,8 +576,9 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
                 assert_not_reached("Received unsupported address family");
         }
 
-        if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) {
-                log_link_warning(link, "Could not print address, ignoring");
+        r = in_addr_to_string(family, &in_addr, &buf);
+        if (r < 0) {
+                log_link_warning_errno(link, r, "Could not print address, ignoring: %m");
                 return 0;
         }
 
@@ -586,12 +586,10 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
         if (r < 0 && r != -ENODATA) {
                 log_link_warning_errno(link, r, "rtnl: cannot get IFA_CACHEINFO attribute, ignoring: %m");
                 return 0;
-        } else if (r >= 0) {
-                if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
-                        valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
-                                                    cinfo.ifa_valid * USEC_PER_SEC,
-                                                    USEC_PER_SEC);
-        }
+        } else if (r >= 0 && cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
+                valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
+                                            cinfo.ifa_valid * USEC_PER_SEC,
+                                            USEC_PER_SEC);
 
         (void) address_get(link, family, &in_addr, prefixlen, &address);
 
@@ -1266,18 +1264,6 @@ static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *
         return 0;
 }
 
-static void dhcp6_prefixes_hash_func(const struct in6_addr *addr, struct siphash *state) {
-        assert(addr);
-
-        siphash24_compress(addr, sizeof(*addr), state);
-}
-
-static int dhcp6_prefixes_compare_func(const struct in6_addr *a, const struct in6_addr *b) {
-        return memcmp(a, b, sizeof(*a));
-}
-
-DEFINE_PRIVATE_HASH_OPS(dhcp6_prefixes_hash_ops, struct in6_addr, dhcp6_prefixes_hash_func, dhcp6_prefixes_compare_func);
-
 int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
         _cleanup_free_ struct in6_addr *a = NULL;
         _cleanup_free_ char *buf = NULL;
@@ -1310,7 +1296,7 @@ int manager_dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
         if (!a)
                 return -ENOMEM;
 
-        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &dhcp6_prefixes_hash_ops);
+        r = hashmap_ensure_allocated(&m->dhcp6_prefixes, &in6_addr_hash_ops);
         if (r < 0)
                 return r;
 
index 1084a3a60b6301aef1fd6dbdae8b74075a8a6558..06fa9d8d32f7ffd66b7f0c301538798f3126403d 100644 (file)
@@ -1,8 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
-#include <arpa/inet.h>
-
 #include "sd-bus.h"
 #include "sd-device.h"
 #include "sd-event.h"
index 3b546528055b2476ec72457cdaae074576acd020..3016f3448bddc9644767010f21f0246ae62e71d4 100644 (file)
@@ -66,12 +66,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
                 if (address->family != AF_INET6)
                         continue;
                 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
-                        char buffer[INET6_ADDRSTRLEN];
+                        _cleanup_free_ char *buffer = NULL;
 
+                        (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
                         log_link_debug(link, "No NDisc route added, gateway %s matches local address",
-                                       inet_ntop(AF_INET6,
-                                                 &address->in_addr.in6,
-                                                 buffer, sizeof(buffer)));
+                                       strnull(buffer));
                         return 0;
                 }
         }
@@ -80,12 +79,11 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
                 if (address->family != AF_INET6)
                         continue;
                 if (in_addr_equal(AF_INET6, &gateway, &address->in_addr)) {
-                        char buffer[INET6_ADDRSTRLEN];
+                        _cleanup_free_ char *buffer = NULL;
 
+                        (void) in_addr_to_string(AF_INET6, &address->in_addr, &buffer);
                         log_link_debug(link, "No NDisc route added, gateway %s matches local address",
-                                       inet_ntop(AF_INET6,
-                                                 &address->in_addr.in6,
-                                                 buffer, sizeof(buffer)));
+                                       strnull(buffer));
                         return 0;
                 }
         }
@@ -559,9 +557,49 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
         return 0;
 }
 
+static int ndisc_prefix_is_black_listed(Link *link, sd_ndisc_router *rt) {
+        int r;
+
+        assert(link);
+        assert(link->network);
+        assert(rt);
+
+        for (r = sd_ndisc_router_option_rewind(rt); ; r = sd_ndisc_router_option_next(rt)) {
+                union in_addr_union a;
+                uint8_t type;
+
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to iterate through options: %m");
+                if (r == 0) /* EOF */
+                        return false;
+
+                r = sd_ndisc_router_option_get_type(rt, &type);
+                if (r < 0)
+                        return log_link_warning_errno(link, r, "Failed to get RA option type: %m");
+
+                if (type != SD_NDISC_OPTION_PREFIX_INFORMATION)
+                        continue;
+
+                r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Failed to get prefix address: %m");
+
+                if (set_contains(link->network->ndisc_black_listed_prefix, &a.in6)) {
+                        if (DEBUG_LOGGING) {
+                                _cleanup_free_ char *b = NULL;
+
+                                (void) in_addr_to_string(AF_INET6, &a, &b);
+                                log_link_debug(link, "Prefix '%s' is black listed, ignoring", strna(b));
+                        }
+
+                        return true;
+                }
+        }
+}
+
 static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
         uint64_t flags;
-        int r = 0;
+        int r;
 
         assert(link);
         assert(link->network);
@@ -583,8 +621,10 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
                 }
         }
 
-        (void) ndisc_router_process_default(link, rt);
-        (void) ndisc_router_process_options(link, rt);
+        if (ndisc_prefix_is_black_listed(link, rt) == 0) {
+                (void) ndisc_router_process_default(link, rt);
+                (void) ndisc_router_process_options(link, rt);
+        }
 
         return r;
 }
@@ -674,3 +714,76 @@ void ndisc_flush(Link *link) {
         link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
         link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
 }
+
+int config_parse_ndisc_black_listed_prefix(
+                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) {
+
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->ndisc_black_listed_prefix = set_free_free(network->ndisc_black_listed_prefix);
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                _cleanup_free_ struct in6_addr *a = NULL;
+                union in_addr_union ip;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse NDISC black listed prefix, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET6, n, &ip);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "NDISC black listed prefix is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                r = set_ensure_allocated(&network->ndisc_black_listed_prefix, &in6_addr_hash_ops);
+                if (r < 0)
+                        return log_oom();
+
+                a = newdup(struct in6_addr, &ip.in6, 1);
+                if (!a)
+                        return log_oom();
+
+                r = set_put(network->ndisc_black_listed_prefix, a);
+                if (r < 0) {
+                        if (r == -EEXIST)
+                                log_syntax(unit, LOG_WARNING, filename, line, r,
+                                           "NDISC black listed prefixs is duplicated, ignoring assignment: %s", n);
+                        else
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to store NDISC black listed prefix '%s', ignoring assignment: %m", n);
+                        continue;
+                }
+
+                TAKE_PTR(a);
+        }
+
+        return 0;
+}
index 0b614bf50ffcc35c1186004a96223129f4726b4b..dc0a44f523096dd5b075d358994f1a9b7ff95cf3 100644 (file)
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 #pragma once
 
+#include "conf-parser.h"
 #include "networkd-link.h"
 #include "time-util.h"
 
@@ -21,3 +22,5 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
 int ndisc_configure(Link *link);
 void ndisc_vacuum(Link *link);
 void ndisc_flush(Link *link);
+
+CONFIG_PARSER_PROTOTYPE(config_parse_ndisc_black_listed_prefix);
index 98c2241fca2ad79c2c74d90468e737e720629448..9ef07ea372be1927393cc95028d4f5284b51aa0d 100644 (file)
@@ -6,6 +6,7 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
 #include "conf-parser.h"
 #include "network-internal.h"
 #include "networkd-conf.h"
+#include "networkd-ndisc.h"
 #include "networkd-network.h"
 #include "vlan-util.h"
 %}
@@ -44,6 +45,7 @@ Network.VLAN,                           config_parse_stacked_netdev,
 Network.MACVLAN,                        config_parse_stacked_netdev,                     NETDEV_KIND_MACVLAN,           offsetof(Network, stacked_netdev_names)
 Network.MACVTAP,                        config_parse_stacked_netdev,                     NETDEV_KIND_MACVTAP,           offsetof(Network, stacked_netdev_names)
 Network.IPVLAN,                         config_parse_stacked_netdev,                     NETDEV_KIND_IPVLAN,            offsetof(Network, stacked_netdev_names)
+Network.IPVTAP,                         config_parse_stacked_netdev,                     NETDEV_KIND_IPVTAP,            offsetof(Network, stacked_netdev_names)
 Network.VXLAN,                          config_parse_stacked_netdev,                     NETDEV_KIND_VXLAN,             offsetof(Network, stacked_netdev_names)
 Network.L2TP,                           config_parse_stacked_netdev,                     NETDEV_KIND_L2TP,              offsetof(Network, stacked_netdev_names)
 Network.MACsec,                         config_parse_stacked_netdev,                     NETDEV_KIND_MACSEC,            offsetof(Network, stacked_netdev_names)
@@ -53,6 +55,7 @@ Network.DHCP,                           config_parse_dhcp,
 Network.DHCPServer,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server)
 Network.LinkLocalAddressing,            config_parse_link_local_address_family_boolean,  0,                             offsetof(Network, link_local)
 Network.IPv4LLRoute,                    config_parse_bool,                               0,                             offsetof(Network, ipv4ll_route)
+Network.DefaultRouteOnDevice,           config_parse_bool,                               0,                             offsetof(Network, default_route_on_device)
 Network.IPv6Token,                      config_parse_ipv6token,                          0,                             offsetof(Network, ipv6_token)
 Network.LLDP,                           config_parse_lldp_mode,                          0,                             offsetof(Network, lldp_mode)
 Network.EmitLLDP,                       config_parse_lldp_emit,                          0,                             offsetof(Network, lldp_emit)
@@ -127,6 +130,8 @@ Route.Type,                             config_parse_route_type,
 Route.InitialCongestionWindow,          config_parse_tcp_window,                         0,                             0
 Route.InitialAdvertisedReceiveWindow,   config_parse_tcp_window,                         0,                             0
 Route.QuickAck,                         config_parse_quickack,                           0,                             0
+Route.FastOpenNoCookie,                 config_parse_fast_open_no_cookie,                0,                             0
+Route.TTLPropagate,                     config_parse_route_ttl_propagate,                0,                             0
 DHCP.ClientIdentifier,                  config_parse_dhcp_client_identifier,             0,                             offsetof(Network, dhcp_client_identifier)
 DHCP.UseDNS,                            config_parse_bool,                               0,                             offsetof(Network, dhcp_use_dns)
 DHCP.UseNTP,                            config_parse_bool,                               0,                             offsetof(Network, dhcp_use_ntp)
@@ -149,13 +154,16 @@ DHCP.RouteTable,                        config_parse_section_route_table,
 DHCP.UseTimezone,                       config_parse_bool,                               0,                             offsetof(Network, dhcp_use_timezone)
 DHCP.IAID,                              config_parse_iaid,                               0,                             0
 DHCP.ListenPort,                        config_parse_uint16,                             0,                             offsetof(Network, dhcp_client_port)
+DHCP.SendRelease,                       config_parse_bool,                               0,                             offsetof(Network, dhcp_send_release)
 DHCP.RapidCommit,                       config_parse_bool,                               0,                             offsetof(Network, rapid_commit)
+DHCP.BlackList,                         config_parse_dhcp_black_listed_ip_address,       0,                             0
 DHCP.ForceDHCPv6PDOtherInformation,     config_parse_bool,                               0,                             offsetof(Network, dhcp6_force_pd_other_information)
 IPv6AcceptRA.UseAutonomousPrefix,       config_parse_bool,                               0,                             offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
 IPv6AcceptRA.UseOnLinkPrefix,           config_parse_bool,                               0,                             offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
 IPv6AcceptRA.UseDNS,                    config_parse_bool,                               0,                             offsetof(Network, ipv6_accept_ra_use_dns)
 IPv6AcceptRA.UseDomains,                config_parse_dhcp_use_domains,                   0,                             offsetof(Network, ipv6_accept_ra_use_domains)
 IPv6AcceptRA.RouteTable,                config_parse_section_route_table,                0,                             0
+IPv6AcceptRA.BlackList,                 config_parse_ndisc_black_listed_prefix,          0,                             0
 DHCPServer.MaxLeaseTimeSec,             config_parse_sec,                                0,                             offsetof(Network, dhcp_server_max_lease_time_usec)
 DHCPServer.DefaultLeaseTimeSec,         config_parse_sec,                                0,                             offsetof(Network, dhcp_server_default_lease_time_usec)
 DHCPServer.EmitDNS,                     config_parse_bool,                               0,                             offsetof(Network, dhcp_server_emit_dns)
@@ -177,11 +185,15 @@ Bridge.MulticastFlood,                  config_parse_tristate,
 Bridge.MulticastToUnicast,              config_parse_tristate,                           0,                             offsetof(Network, multicast_to_unicast)
 Bridge.NeighborSuppression,             config_parse_tristate,                           0,                             offsetof(Network, neighbor_suppression)
 Bridge.Learning,                        config_parse_tristate,                           0,                             offsetof(Network, learning)
+Bridge.ProxyARP,                        config_parse_tristate,                           0,                             offsetof(Network, bridge_proxy_arp)
+Bridge.ProxyARPWiFi,                    config_parse_tristate,                           0,                             offsetof(Network, bridge_proxy_arp_wifi)
 Bridge.Priority,                        config_parse_bridge_port_priority,               0,                             offsetof(Network, priority)
+Bridge.MulticastRouter,                 config_parse_multicast_router,                   0,                             offsetof(Network, multicast_router)
 BridgeFDB.MACAddress,                   config_parse_fdb_hwaddr,                         0,                             0
 BridgeFDB.VLANId,                       config_parse_fdb_vlan_id,                        0,                             0
 BridgeFDB.Destination,                  config_parse_fdb_destination,                    0,                             0
 BridgeFDB.VNI,                          config_parse_fdb_vxlan_vni,                      0,                             0
+BridgeFDB.AssociatedWith,               config_parse_fdb_ntf_flags,                      0,                             0
 BridgeVLAN.PVID,                        config_parse_brvlan_pvid,                        0,                             0
 BridgeVLAN.VLAN,                        config_parse_brvlan_vlan,                        0,                             0
 BridgeVLAN.EgressUntagged,              config_parse_brvlan_untagged,                    0,                             0
index 6e0e1eae08dfd19c3fa4f73320abe2c9b18d6dbc..a5e7cad58a4c9b910d4bd647e8397fe26912a424 100644 (file)
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <net/if.h>
+#include <netinet/in.h>
 #include <linux/netdevice.h>
 
 #include "alloc-util.h"
@@ -141,24 +143,6 @@ static int network_resolve_stacked_netdevs(Network *network) {
         return 0;
 }
 
-static uint32_t network_get_stacked_netdevs_mtu(Network *network) {
-        uint32_t mtu = 0;
-        NetDev *dev;
-        Iterator i;
-
-        HASHMAP_FOREACH(dev, network->stacked_netdevs, i)
-                if (dev->kind == NETDEV_KIND_VLAN && dev->mtu > 0)
-                        /* See vlan_dev_change_mtu() in kernel.
-                         * Note that the additional 4bytes may not be necessary for all devices. */
-                        mtu = MAX(mtu, dev->mtu + 4);
-
-                else if (dev->kind == NETDEV_KIND_MACVLAN && dev->mtu > mtu)
-                        /* See macvlan_change_mtu() in kernel. */
-                        mtu = dev->mtu;
-
-        return mtu;
-}
-
 int network_verify(Network *network) {
         Address *address, *address_next;
         Route *route, *route_next;
@@ -167,7 +151,6 @@ int network_verify(Network *network) {
         AddressLabel *label, *label_next;
         Prefix *prefix, *prefix_next;
         RoutingPolicyRule *rule, *rule_next;
-        uint32_t mtu;
 
         assert(network);
         assert(network->filename);
@@ -250,16 +233,7 @@ int network_verify(Network *network) {
         if (network->ip_masquerade)
                 network->ip_forward |= ADDRESS_FAMILY_IPV4;
 
-        network->mtu_is_set = network->mtu > 0;
-        mtu = network_get_stacked_netdevs_mtu(network);
-        if (network->mtu < mtu) {
-                if (network->mtu_is_set)
-                        log_notice("%s: Bumping MTUBytes= from %"PRIu32" to %"PRIu32" because of stacked device",
-                                   network->filename, network->mtu, mtu);
-                network->mtu = mtu;
-        }
-
-        if (network->mtu_is_set && network->dhcp_use_mtu) {
+        if (network->mtu > 0 && network->dhcp_use_mtu) {
                 log_warning("%s: MTUBytes= in [Link] section and UseMTU= in [DHCP] section are set. "
                             "Disabling UseMTU=.", network->filename);
                 network->dhcp_use_mtu = false;
@@ -386,7 +360,10 @@ int network_load_one(Manager *manager, const char *filename) {
                 .multicast_to_unicast = -1,
                 .neighbor_suppression = -1,
                 .learning = -1,
+                .bridge_proxy_arp = -1,
+                .bridge_proxy_arp_wifi = -1,
                 .priority = LINK_BRIDGE_PORT_PRIORITY_INVALID,
+                .multicast_router = _MULTICAST_ROUTER_INVALID,
 
                 .lldp_mode = LLDP_MODE_ROUTERS_ONLY,
 
@@ -449,6 +426,11 @@ int network_load_one(Manager *manager, const char *filename) {
         if (r < 0)
                 log_warning_errno(r, "%s: Failed to add IPv4LL route, ignoring: %m", network->filename);
 
+        r = network_add_default_route_on_device(network);
+        if (r < 0)
+                log_warning_errno(r, "%s: Failed to add default route on device, ignoring: %m",
+                                  network->filename);
+
         r = ordered_hashmap_ensure_allocated(&manager->networks, &string_hash_ops);
         if (r < 0)
                 return r;
@@ -512,7 +494,7 @@ static Network *network_free(Network *network) {
         free(network->dhcp_vendor_class_identifier);
         strv_free(network->dhcp_user_class);
         free(network->dhcp_hostname);
-
+        set_free(network->dhcp_black_listed_ip);
         free(network->mac);
 
         strv_free(network->ntp);
@@ -523,6 +505,7 @@ static Network *network_free(Network *network) {
 
         ordered_set_free_free(network->router_search_domains);
         free(network->router_dns);
+        set_free_free(network->ndisc_black_listed_prefix);
 
         free(network->bridge_name);
         free(network->bond_name);
@@ -698,8 +681,8 @@ int config_parse_stacked_netdev(const char *unit,
         assert(data);
         assert(IN_SET(kind,
                       NETDEV_KIND_VLAN, NETDEV_KIND_MACVLAN, NETDEV_KIND_MACVTAP,
-                      NETDEV_KIND_IPVLAN, NETDEV_KIND_VXLAN, NETDEV_KIND_L2TP,
-                      NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
+                      NETDEV_KIND_IPVLAN, NETDEV_KIND_IPVTAP, NETDEV_KIND_VXLAN,
+                      NETDEV_KIND_L2TP, NETDEV_KIND_MACSEC, _NETDEV_KIND_TUNNEL));
 
         if (!ifname_valid(rvalue)) {
                 log_syntax(unit, LOG_ERR, filename, line, 0,
@@ -1115,7 +1098,8 @@ int config_parse_dhcp_server_dns(
 
         for (;;) {
                 _cleanup_free_ char *w = NULL;
-                struct in_addr a, *m;
+                union in_addr_union a;
+                struct in_addr *m;
 
                 r = extract_first_word(&p, &w, NULL, 0);
                 if (r == -ENOMEM)
@@ -1128,9 +1112,10 @@ int config_parse_dhcp_server_dns(
                 if (r == 0)
                         break;
 
-                if (inet_pton(AF_INET, w, &a) <= 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse DNS server address, ignoring: %s", w);
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DNS server address '%s', ignoring assignment: %m", w);
                         continue;
                 }
 
@@ -1138,7 +1123,7 @@ int config_parse_dhcp_server_dns(
                 if (!m)
                         return log_oom();
 
-                m[n->n_dhcp_server_dns++] = a;
+                m[n->n_dhcp_server_dns++] = a.in;
                 n->dhcp_server_dns = m;
         }
 
@@ -1275,7 +1260,8 @@ int config_parse_dhcp_server_ntp(
 
         for (;;) {
                 _cleanup_free_ char *w = NULL;
-                struct in_addr a, *m;
+                union in_addr_union a;
+                struct in_addr *m;
 
                 r = extract_first_word(&p, &w, NULL, 0);
                 if (r == -ENOMEM)
@@ -1288,9 +1274,10 @@ int config_parse_dhcp_server_ntp(
                 if (r == 0)
                         return 0;
 
-                if (inet_pton(AF_INET, w, &a) <= 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, 0,
-                                   "Failed to parse NTP server address, ignoring: %s", w);
+                r = in_addr_from_string(AF_INET, w, &a);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse NTP server address '%s', ignoring: %m", w);
                         continue;
                 }
 
@@ -1298,7 +1285,7 @@ int config_parse_dhcp_server_ntp(
                 if (!m)
                         return log_oom();
 
-                m[n->n_dhcp_server_ntp++] = a;
+                m[n->n_dhcp_server_ntp++] = a.in;
                 n->dhcp_server_ntp = m;
         }
 }
@@ -1620,6 +1607,66 @@ int config_parse_dhcp_max_attempts(
         return 0;
 }
 
+int config_parse_dhcp_black_listed_ip_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) {
+
+        Network *network = data;
+        const char *p;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
+                return 0;
+        }
+
+        for (p = rvalue;;) {
+                _cleanup_free_ char *n = NULL;
+                union in_addr_union ip;
+
+                r = extract_first_word(&p, &n, NULL, 0);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
+                                   rvalue);
+                        return 0;
+                }
+                if (r == 0)
+                        return 0;
+
+                r = in_addr_from_string(AF_INET, n, &ip);
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
+                        continue;
+                }
+
+                r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
+                if (r < 0)
+                        return log_oom();
+
+                r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+                if (r < 0)
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
+        }
+
+        return 0;
+}
+
 DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains,
                          "Failed to parse DHCP use domains setting");
 
@@ -1631,16 +1678,6 @@ static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
 
-DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
-
-static const char* const lldp_mode_table[_LLDP_MODE_MAX] = {
-        [LLDP_MODE_NO] = "no",
-        [LLDP_MODE_YES] = "yes",
-        [LLDP_MODE_ROUTERS_ONLY] = "routers-only",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES);
-
 int config_parse_iaid(const char *unit,
                       const char *filename,
                       unsigned line,
index 9ee8fb72b8d73d52a606f1490cde96559db95cca..d2a0b8c5f14ee6d59e637d4033d7da34390ae7a7 100644 (file)
@@ -8,12 +8,14 @@
 #include "conf-parser.h"
 #include "dhcp-identifier.h"
 #include "hashmap.h"
+#include "netdev/bridge.h"
 #include "netdev/netdev.h"
 #include "networkd-address-label.h"
 #include "networkd-address.h"
 #include "networkd-brvlan.h"
 #include "networkd-fdb.h"
 #include "networkd-ipv6-proxy-ndp.h"
+#include "networkd-lldp-rx.h"
 #include "networkd-lldp-tx.h"
 #include "networkd-neighbor.h"
 #include "networkd-radv.h"
@@ -58,14 +60,6 @@ typedef enum DHCPUseDomains {
         _DHCP_USE_DOMAINS_INVALID = -1,
 } DHCPUseDomains;
 
-typedef enum LLDPMode {
-        LLDP_MODE_NO = 0,
-        LLDP_MODE_YES = 1,
-        LLDP_MODE_ROUTERS_ONLY = 2,
-        _LLDP_MODE_MAX,
-        _LLDP_MODE_INVALID = -1,
-} LLDPMode;
-
 typedef struct DUID {
         /* Value of Type in [DHCP] section */
         DUIDType type;
@@ -134,7 +128,9 @@ struct Network {
         bool rapid_commit;
         bool dhcp_use_hostname;
         bool dhcp_route_table_set;
+        bool dhcp_send_release;
         DHCPUseDomains dhcp_use_domains;
+        Set *dhcp_black_listed_ip;
 
         /* DHCP Server Support */
         bool dhcp_server;
@@ -155,6 +151,8 @@ struct Network {
         AddressFamilyBoolean link_local;
         bool ipv4ll_route;
 
+        bool default_route_on_device;
+
         /* IPv6 prefix delegation support */
         RADVPrefixDelegation router_prefix_delegation;
         usec_t router_lifetime_usec;
@@ -181,8 +179,11 @@ struct Network {
         int multicast_to_unicast;
         int neighbor_suppression;
         int learning;
+        int bridge_proxy_arp;
+        int bridge_proxy_arp_wifi;
         uint32_t cost;
         uint16_t priority;
+        MulticastRouter multicast_router;
 
         bool use_br_vlan;
         uint16_t pvid;
@@ -213,13 +214,13 @@ struct Network {
         DHCPUseDomains ipv6_accept_ra_use_domains;
         uint32_t ipv6_accept_ra_route_table;
         bool ipv6_accept_ra_route_table_set;
+        Set *ndisc_black_listed_prefix;
 
         union in_addr_union ipv6_token;
         IPv6PrivacyExtensions ipv6_privacy_extensions;
 
         struct ether_addr *mac;
         uint32_t mtu;
-        bool mtu_is_set; /* Indicate MTUBytes= is specified. */
         int arp;
         int multicast;
         int allmulticast;
@@ -305,12 +306,12 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_privacy_extensions);
 CONFIG_PARSER_PROTOTYPE(config_parse_hostname);
 CONFIG_PARSER_PROTOTYPE(config_parse_timezone);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_dns);
+CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_black_listed_ip_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns);
 CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_server_ntp);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_negative_trust_anchors);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
-CONFIG_PARSER_PROTOTYPE(config_parse_lldp_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
 CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
 CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
@@ -333,8 +334,5 @@ IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
 const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
 DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
 
-const char* lldp_mode_to_string(LLDPMode m) _const_;
-LLDPMode lldp_mode_from_string(const char *s) _pure_;
-
 const char* radv_prefix_delegation_to_string(RADVPrefixDelegation i) _const_;
 RADVPrefixDelegation radv_prefix_delegation_from_string(const char *s) _pure_;
index 379077cbfde9c5b17303de832f5228fb9d897c73..b21e7dfd86f2a2c3be846b402111ba7b86a8204e 100644 (file)
@@ -59,7 +59,9 @@ int route_new(Route **ret) {
                 .table = RT_TABLE_MAIN,
                 .lifetime = USEC_INFINITY,
                 .quickack = -1,
+                .fast_open_no_cookie = -1,
                 .gateway_onlink = -1,
+                .ttl_propagate = -1,
         };
 
         *ret = TAKE_PTR(route);
@@ -616,6 +618,12 @@ int route_configure(
                         return log_link_error_errno(link, r, "Could not append RTA_OIF attribute: %m");
         }
 
+        if (route->ttl_propagate >= 0) {
+                r = sd_netlink_message_append_u8(req, RTA_TTL_PROPAGATE, route->ttl_propagate);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append RTA_TTL_PROPAGATE attribute: %m");
+        }
+
         r = sd_netlink_message_open_container(req, RTA_METRICS);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
@@ -638,12 +646,18 @@ int route_configure(
                         return log_link_error_errno(link, r, "Could not append RTAX_INITRWND attribute: %m");
         }
 
-        if (route->quickack != -1) {
+        if (route->quickack >= 0) {
                 r = sd_netlink_message_append_u32(req, RTAX_QUICKACK, route->quickack);
                 if (r < 0)
                         return log_link_error_errno(link, r, "Could not append RTAX_QUICKACK attribute: %m");
         }
 
+        if (route->fast_open_no_cookie >= 0) {
+                r = sd_netlink_message_append_u32(req, RTAX_FASTOPEN_NO_COOKIE, route->fast_open_no_cookie);
+                if (r < 0)
+                        return log_link_error_errno(link, r, "Could not append RTAX_FASTOPEN_NO_COOKIE attribute: %m");
+        }
+
         r = sd_netlink_message_close_container(req);
         if (r < 0)
                 return log_link_error_errno(link, r, "Could not append RTA_METRICS attribute: %m");
@@ -705,6 +719,30 @@ int network_add_ipv4ll_route(Network *network) {
         return 0;
 }
 
+int network_add_default_route_on_device(Network *network) {
+        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+        int r;
+
+        assert(network);
+
+        if (!network->default_route_on_device)
+                return 0;
+
+        /* DefaultRouteOnDevice= is in [Network] section. */
+        r = route_new_static(network, NULL, 0, &n);
+        if (r < 0)
+                return r;
+
+        r = in_addr_from_string(AF_INET, "169.254.0.0", &n->dst);
+        if (r < 0)
+                return r;
+
+        n->family = AF_INET;
+
+        TAKE_PTR(n);
+        return 0;
+}
+
 int config_parse_gateway(
                 const char *unit,
                 const char *filename,
@@ -1197,6 +1235,44 @@ int config_parse_quickack(
         return 0;
 }
 
+int config_parse_fast_open_no_cookie(
+                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_(route_free_or_set_invalidp) Route *n = NULL;
+        Network *network = userdata;
+        int k, r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, k,
+                           "Failed to parse TCP fastopen no cookie, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->fast_open_no_cookie = k;
+        TAKE_PTR(n);
+        return 0;
+}
+
 int config_parse_route_mtu(
                 const char *unit,
                 const char *filename,
@@ -1231,6 +1307,45 @@ int config_parse_route_mtu(
         return 0;
 }
 
+int config_parse_route_ttl_propagate(
+                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) {
+
+        Network *network = userdata;
+        _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
+        int r, k;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = route_new_static(network, filename, section_line, &n);
+        if (r < 0)
+                return r;
+
+        k = parse_boolean(rvalue);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, k,
+                           "Failed to parse TTLPropagate= value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        n->ttl_propagate = k;
+
+        TAKE_PTR(n);
+        return 0;
+}
+
 int route_section_verify(Route *route, Network *network) {
         if (section_is_invalid(route->section))
                 return -EINVAL;
index 1e8320fdc087814ca3c74af89a3f10aeb0c548a4..3c0ac896aea5a26961c11dea9cae0a6cd331fb2d 100644 (file)
@@ -17,6 +17,8 @@ struct Route {
 
         int family;
         int quickack;
+        int fast_open_no_cookie;
+        int ttl_propagate;
 
         unsigned char dst_prefixlen;
         unsigned char src_prefixlen;
@@ -61,6 +63,7 @@ int route_section_verify(Route *route, Network *network);
 DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
 
 int network_add_ipv4ll_route(Network *network);
+int network_add_default_route_on_device(Network *network);
 
 CONFIG_PARSER_PROTOTYPE(config_parse_gateway);
 CONFIG_PARSER_PROTOTYPE(config_parse_preferred_src);
@@ -74,4 +77,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_route_protocol);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_tcp_window);
 CONFIG_PARSER_PROTOTYPE(config_parse_quickack);
+CONFIG_PARSER_PROTOTYPE(config_parse_fast_open_no_cookie);
+CONFIG_PARSER_PROTOTYPE(config_parse_route_ttl_propagate);
 CONFIG_PARSER_PROTOTYPE(config_parse_route_mtu);
index 28699ba2369d9f070df9fe3b90196e475df6d16a..4ee0b5489ef7002c5ae3fa90bb5de9c53898e8ad 100644 (file)
@@ -2,6 +2,7 @@
 #pragma once
 
 #include <inttypes.h>
+#include <netinet/in.h>
 #include <linux/fib_rules.h>
 #include <stdbool.h>
 
index 4b04aa0463c91c862470ad2411d1db433e50e088..090f3777a5ae2de7304c05f25c0e8119b018bf3d 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <netinet/in.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
index 21ee97e84ea9d211051ecad6a34dae6d9cb57c12..23fcea666e6eeeb73dd994073c35b8114ff33c82 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1+ */
 
+#include <arpa/inet.h>
 #include <sys/param.h>
 
 #include "sd-device.h"
 static void test_deserialize_in_addr(void) {
         _cleanup_free_ struct in_addr *addresses = NULL;
         _cleanup_free_ struct in6_addr *addresses6 = NULL;
-        struct in_addr  a, b, c;
-        struct in6_addr d, e, f;
+        union in_addr_union a, b, c, d, e, f;
         int size;
         const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8";
 
-        assert_se(inet_pton(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) == 0);
-        assert_se(inet_pton(AF_INET6, "192.168.0.1", &d) == 0);
+        assert_se(in_addr_from_string(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) < 0);
+        assert_se(in_addr_from_string(AF_INET6, "192.168.0.1", &d) < 0);
 
-        assert_se(inet_pton(AF_INET, "192.168.0.1", &a) == 1);
-        assert_se(inet_pton(AF_INET, "192.168.0.2", &b) == 1);
-        assert_se(inet_pton(AF_INET, "192.168.0.3", &c) == 1);
-        assert_se(inet_pton(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) == 1);
-        assert_se(inet_pton(AF_INET6, "::1", &e) == 1);
-        assert_se(inet_pton(AF_INET6, "1:0:0:0:0:0:0:8", &f) == 1);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.1", &a) >= 0);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.2", &b) >= 0);
+        assert_se(in_addr_from_string(AF_INET, "192.168.0.3", &c) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "::1", &e) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "1:0:0:0:0:0:0:8", &f) >= 0);
 
         assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0);
         assert_se(size == 3);
-        assert_se(!memcmp(&a, &addresses[0], sizeof(struct in_addr)));
-        assert_se(!memcmp(&b, &addresses[1], sizeof(struct in_addr)));
-        assert_se(!memcmp(&c, &addresses[2], sizeof(struct in_addr)));
+        assert_se(in_addr_equal(AF_INET, &a, (union in_addr_union *) &addresses[0]));
+        assert_se(in_addr_equal(AF_INET, &b, (union in_addr_union *) &addresses[1]));
+        assert_se(in_addr_equal(AF_INET, &c, (union in_addr_union *) &addresses[2]));
 
         assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0);
         assert_se(size == 3);
-        assert_se(!memcmp(&d, &addresses6[0], sizeof(struct in6_addr)));
-        assert_se(!memcmp(&e, &addresses6[1], sizeof(struct in6_addr)));
-        assert_se(!memcmp(&f, &addresses6[2], sizeof(struct in6_addr)));
+        assert_se(in_addr_equal(AF_INET6, &d, (union in_addr_union *) &addresses6[0]));
+        assert_se(in_addr_equal(AF_INET6, &e, (union in_addr_union *) &addresses6[1]));
+        assert_se(in_addr_equal(AF_INET6, &f, (union in_addr_union *) &addresses6[2]));
 }
 
 static void test_deserialize_dhcp_routes(void) {
@@ -146,13 +146,13 @@ static void test_address_equality(void) {
         a2->family = AF_INET;
         assert_se(address_equal(a1, a2));
 
-        assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a1->in_addr) >= 0);
         assert_se(!address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.9", &a2->in_addr) >= 0);
         assert_se(address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.10", &a1->in_addr_peer) >= 0);
         assert_se(address_equal(a1, a2));
-        assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in));
+        assert_se(in_addr_from_string(AF_INET, "192.168.3.11", &a2->in_addr_peer) >= 0);
         assert_se(address_equal(a1, a2));
         a1->prefixlen = 10;
         assert_se(!address_equal(a1, a2));
@@ -163,14 +163,14 @@ static void test_address_equality(void) {
         assert_se(!address_equal(a1, a2));
 
         a2->family = AF_INET6;
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6));
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6));
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr) >= 0);
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr) >= 0);
         assert_se(address_equal(a1, a2));
 
         a2->prefixlen = 8;
         assert_se(address_equal(a1, a2));
 
-        assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6));
+        assert_se(in_addr_from_string(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr) >= 0);
         assert_se(!address_equal(a1, a2));
 }
 
index e1f9a812fbb8c863ffb0f2c3aab44e1bcf4d3f48..e38b5603c22a043d512be3880711eb534d5a7106 100644 (file)
@@ -164,7 +164,7 @@ static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *
                         log_link_warning_errno(l, r, "Failed to process RTNL link message, ignoring: %m");
 
                 r = link_update_monitor(l);
-                if (r < 0)
+                if (r < 0 && r != -ENODATA)
                         log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m");
 
                 break;
@@ -253,8 +253,8 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
 
         HASHMAP_FOREACH(l, m->links, i) {
                 r = link_update_monitor(l);
-                if (r < 0)
-                        log_link_warning_errno(l, r, "Failed to update monitor information: %m");
+                if (r < 0 && r != -ENODATA)
+                        log_link_warning_errno(l, r, "Failed to update link state, ignoring: %m");
         }
 
         if (manager_configured(m))
index ab0c34692f1ce22b34157e16762f189a18595002..6c0a36990291832e7c2c36953515c5ecb91448c2 100644 (file)
@@ -80,7 +80,7 @@ static int retrieve_key(key_serial_t serial, char ***ret) {
                 if (n < m)
                         break;
 
-                explicit_bzero_safe(p, n);
+                explicit_bzero_safe(p, m);
 
                 if (m > LONG_MAX / 2) /* overflow check */
                         return -ENOMEM;
index 1bd8835633c2d31202ff53d080e8be56b2bb9a67..f16c2db739625598add525dd43034fcee5589095 100644 (file)
@@ -909,7 +909,7 @@ bool efi_loader_entry_name_valid(const char *s) {
         if (strlen(s) > FILENAME_MAX) /* Make sure entry names fit in filenames */
                 return false;
 
-        return in_charset(s, ALPHANUMERICAL "-_.");
+        return in_charset(s, ALPHANUMERICAL "+-_.");
 }
 
 char *efi_tilt_backslashes(char *s) {
index 073f800b3464301eae6595549b71a3e8ab2cedc3..782d80af16aac0a2d77e591bd872b95e445340e2 100644 (file)
@@ -2296,9 +2296,9 @@ static int json_parse_internal(
                 column = &column_buffer;
 
         for (;;) {
+                _cleanup_(json_variant_unrefp) JsonVariant *add = NULL;
                 _cleanup_free_ char *string = NULL;
                 unsigned line_token, column_token;
-                JsonVariant *add = NULL;
                 JsonStack *current;
                 JsonValue value;
                 int token;
@@ -2591,7 +2591,7 @@ static int json_parse_internal(
                                 goto finish;
                         }
 
-                        current->elements[current->n_elements++] = add;
+                        current->elements[current->n_elements++] = TAKE_PTR(add);
                 }
         }
 
index c80a67cdde45819decc52623a0cf839c767ac667..aa0423ccad73af5c70c941196ae65676d36031fc 100644 (file)
@@ -164,6 +164,8 @@ shared_sources = files('''
         uid-range.c
         uid-range.h
         utmp-wtmp.h
+        varlink.c
+        varlink.h
         verbs.c
         verbs.h
         vlan-util.c
index 7f23e5410239e425b65371d605ed95d99efd6e4a..0e114a7b49a94869b72844444b216e6e3ca8b626 100644 (file)
@@ -386,7 +386,7 @@ static bool can_s2h(void) {
         r = access("/sys/class/rtc/rtc0/wakealarm", W_OK);
         if (r < 0) {
                 log_full(errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
-                         "/sys/class/rct/rct0/wakealarm is not writable %m");
+                         "/sys/class/rtc/rtc0/wakealarm is not writable %m");
                 return false;
         }
 
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
new file mode 100644 (file)
index 0000000..3256a93
--- /dev/null
@@ -0,0 +1,2390 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <sys/poll.h>
+
+#include "alloc-util.h"
+#include "errno-util.h"
+#include "fd-util.h"
+#include "hashmap.h"
+#include "list.h"
+#include "process-util.h"
+#include "set.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "string-util.h"
+#include "strv.h"
+#include "time-util.h"
+#include "umask-util.h"
+#include "user-util.h"
+#include "varlink.h"
+
+#define VARLINK_DEFAULT_CONNECTIONS_MAX 4096U
+#define VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX 1024U
+
+#define VARLINK_DEFAULT_TIMEOUT_USEC (45U*USEC_PER_SEC)
+#define VARLINK_BUFFER_MAX (16U*1024U*1024U)
+#define VARLINK_READ_SIZE (64U*1024U)
+
+typedef enum VarlinkState {
+        /* Client side states */
+        VARLINK_IDLE_CLIENT,
+        VARLINK_AWAITING_REPLY,
+        VARLINK_CALLING,
+        VARLINK_CALLED,
+        VARLINK_PROCESSING_REPLY,
+
+        /* Server side states */
+        VARLINK_IDLE_SERVER,
+        VARLINK_PROCESSING_METHOD,
+        VARLINK_PROCESSING_METHOD_MORE,
+        VARLINK_PROCESSING_METHOD_ONEWAY,
+        VARLINK_PROCESSED_METHOD,
+        VARLINK_PROCESSED_METHOD_MORE,
+        VARLINK_PENDING_METHOD,
+        VARLINK_PENDING_METHOD_MORE,
+
+        /* Common states (only during shutdown) */
+        VARLINK_PENDING_DISCONNECT,
+        VARLINK_PENDING_TIMEOUT,
+        VARLINK_PROCESSING_DISCONNECT,
+        VARLINK_PROCESSING_TIMEOUT,
+        VARLINK_PROCESSING_FAILURE,
+        VARLINK_DISCONNECTED,
+
+        _VARLINK_STATE_MAX,
+        _VARLINK_STATE_INVALID = -1
+} VarlinkState;
+
+/* Tests whether we are not yet disconnected. Note that this is true during all states where the connection
+ * is still good for something, and false only when it's dead for good. This means: when we are
+ * asynchronously connecting to a peer and the connect() is still pending, then this will return 'true', as
+ * the connection is still good, and we are likely to be able to properly operate on it soon. */
+#define VARLINK_STATE_IS_ALIVE(state)                   \
+        IN_SET(state,                                   \
+               VARLINK_IDLE_CLIENT,                     \
+               VARLINK_AWAITING_REPLY,                  \
+               VARLINK_CALLING,                         \
+               VARLINK_CALLED,                          \
+               VARLINK_PROCESSING_REPLY,                \
+               VARLINK_IDLE_SERVER,                     \
+               VARLINK_PROCESSING_METHOD,               \
+               VARLINK_PROCESSING_METHOD_MORE,          \
+               VARLINK_PROCESSING_METHOD_ONEWAY,        \
+               VARLINK_PROCESSED_METHOD,                \
+               VARLINK_PROCESSED_METHOD_MORE,           \
+               VARLINK_PENDING_METHOD,                  \
+               VARLINK_PENDING_METHOD_MORE)
+
+struct Varlink {
+        unsigned n_ref;
+
+        VarlinkServer *server;
+
+        VarlinkState state;
+        bool connecting; /* This boolean indicates whether the socket fd we are operating on is currently
+                          * processing an asynchronous connect(). In that state we watch the socket for
+                          * EPOLLOUT, but we refrain from calling read() or write() on the socket as that
+                          * will trigger ENOTCONN. Note that this boolean is kept separate from the
+                          * VarlinkState above on purpose: while the connect() is still not complete we
+                          * already want to allow queuing of messages and similar. Thus it's nice to keep
+                          * these two state concepts separate: the VarlinkState encodes what our own view of
+                          * the connection is, i.e. whether we think it's a server, a client, and has
+                          * something queued already, while 'connecting' tells us a detail about the
+                          * transport used below, that should have no effect on how we otherwise accept and
+                          * process operations from the user.
+                          *
+                          * Or to say this differently: VARLINK_STATE_IS_ALIVE(state) tells you whether the
+                          * connection is good to use, even if it might not be fully connected
+                          * yet. connecting=true then informs you that actually we are still connecting, and
+                          * the connection is actually not established yet and thus any requests you enqueue
+                          * now will still work fine but will be queued only, not sent yet, but that
+                          * shouldn't stop you from using the connection, since eventually whatever you queue
+                          * *will* be sent.
+                          *
+                          * Or to say this even differently: 'state' is a high-level ("application layer"
+                          * high, if you so will) state, while 'conecting' is a low-level ("transport layer"
+                          * low, if you so will) state, and while they are not entirely unrelated and
+                          * sometimes propagate effects to each other they are only asynchronously connected
+                          * at most. */
+        unsigned n_pending;
+
+        int fd;
+
+        char *input_buffer; /* valid data starts at input_buffer_index, ends at input_buffer_index+input_buffer_size */
+        size_t input_buffer_allocated;
+        size_t input_buffer_index;
+        size_t input_buffer_size;
+        size_t input_buffer_unscanned;
+
+        char *output_buffer; /* valid data starts at output_buffer_index, ends at output_buffer_index+output_buffer_size */
+        size_t output_buffer_allocated;
+        size_t output_buffer_index;
+        size_t output_buffer_size;
+
+        VarlinkReply reply_callback;
+
+        JsonVariant *current;
+        JsonVariant *reply;
+
+        struct ucred ucred;
+        bool ucred_acquired:1;
+
+        bool write_disconnected:1;
+        bool read_disconnected:1;
+        bool prefer_read_write:1;
+        bool got_pollhup:1;
+
+        usec_t timestamp;
+        usec_t timeout;
+
+        void *userdata;
+        char *description;
+
+        sd_event *event;
+        sd_event_source *io_event_source;
+        sd_event_source *time_event_source;
+        sd_event_source *quit_event_source;
+        sd_event_source *defer_event_source;
+};
+
+typedef struct VarlinkServerSocket VarlinkServerSocket;
+
+struct VarlinkServerSocket {
+        VarlinkServer *server;
+
+        int fd;
+        char *address;
+
+        sd_event_source *event_source;
+
+        LIST_FIELDS(VarlinkServerSocket, sockets);
+};
+
+struct VarlinkServer {
+        unsigned n_ref;
+        VarlinkServerFlags flags;
+
+        LIST_HEAD(VarlinkServerSocket, sockets);
+
+        Hashmap *methods;
+        VarlinkConnect connect_callback;
+
+        sd_event *event;
+        int64_t event_priority;
+
+        unsigned n_connections;
+        Hashmap *by_uid;
+
+        void *userdata;
+        char *description;
+
+        unsigned connections_max;
+        unsigned connections_per_uid_max;
+};
+
+static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
+        [VARLINK_IDLE_CLIENT]              = "idle-client",
+        [VARLINK_AWAITING_REPLY]           = "awaiting-reply",
+        [VARLINK_CALLING]                  = "calling",
+        [VARLINK_CALLED]                   = "called",
+        [VARLINK_PROCESSING_REPLY]         = "processing-reply",
+        [VARLINK_IDLE_SERVER]              = "idle-server",
+        [VARLINK_PROCESSING_METHOD]        = "processing-method",
+        [VARLINK_PROCESSING_METHOD_MORE]   = "processing-method-more",
+        [VARLINK_PROCESSING_METHOD_ONEWAY] = "processing-method-oneway",
+        [VARLINK_PROCESSED_METHOD]         = "processed-method",
+        [VARLINK_PROCESSED_METHOD_MORE]    = "processed-method-more",
+        [VARLINK_PENDING_METHOD]           = "pending-method",
+        [VARLINK_PENDING_METHOD_MORE]      = "pending-method-more",
+        [VARLINK_PENDING_DISCONNECT]       = "pending-disconnect",
+        [VARLINK_PENDING_TIMEOUT]          = "pending-timeout",
+        [VARLINK_PROCESSING_DISCONNECT]    = "processing-disconnect",
+        [VARLINK_PROCESSING_TIMEOUT]       = "processing-timeout",
+        [VARLINK_PROCESSING_FAILURE]       = "processing-failure",
+        [VARLINK_DISCONNECTED]             = "disconnected",
+};
+
+DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(varlink_state, VarlinkState);
+
+#define varlink_log_errno(v, error, fmt, ...)                           \
+        log_debug_errno(error, "%s: " fmt, varlink_description(v), ##__VA_ARGS__)
+
+#define varlink_log(v, fmt, ...)                                        \
+        log_debug("%s: " fmt, varlink_description(v), ##__VA_ARGS__)
+
+#define varlink_server_log_errno(s, error, fmt, ...) \
+        log_debug_errno(error, "%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
+
+#define varlink_server_log(s, fmt, ...) \
+        log_debug("%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
+
+static inline const char *varlink_description(Varlink *v) {
+        return strna(v ? v->description : NULL);
+}
+
+static inline const char *varlink_server_description(VarlinkServer *s) {
+        return strna(s ? s->description : NULL);
+}
+
+static void varlink_set_state(Varlink *v, VarlinkState state) {
+        assert(v);
+        assert(state >= 0 && state < _VARLINK_STATE_MAX);
+
+        if (v->state < 0)
+                varlink_log(v, "varlink: setting state %s",
+                            varlink_state_to_string(state));
+        else
+                varlink_log(v, "varlink: changing state %s â†’ %s",
+                            varlink_state_to_string(v->state),
+                            varlink_state_to_string(state));
+
+        v->state = state;
+}
+
+static int varlink_new(Varlink **ret) {
+        Varlink *v;
+
+        assert(ret);
+
+        /* Here use new0 as the below structured initializer is nested. */
+        v = new0(Varlink, 1);
+        if (!v)
+                return -ENOMEM;
+
+        *v = (Varlink) {
+                .n_ref = 1,
+                .fd = -1,
+
+                .state = _VARLINK_STATE_INVALID,
+
+                .ucred.uid = UID_INVALID,
+                .ucred.gid = GID_INVALID,
+
+                .timestamp = USEC_INFINITY,
+                .timeout = VARLINK_DEFAULT_TIMEOUT_USEC
+        };
+
+        *ret = v;
+        return 0;
+}
+
+int varlink_connect_address(Varlink **ret, const char *address) {
+        _cleanup_(varlink_unrefp) Varlink *v = NULL;
+        union sockaddr_union sockaddr;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(address, -EINVAL);
+
+        r = sockaddr_un_set_path(&sockaddr.un, address);
+        if (r < 0)
+                return r;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return r;
+
+        v->fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (v->fd < 0)
+                return -errno;
+
+        if (connect(v->fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) {
+                if (!IN_SET(errno, EAGAIN, EINPROGRESS))
+                        return -errno;
+
+                v->connecting = true; /* We are asynchronously connecting, i.e. the connect() is being
+                                       * processed in the background. As long as that's the case the socket
+                                       * is in a special state: it's there, we can poll it for EPOLLOUT, but
+                                       * if we attempt to write() to it before we see EPOLLOUT we'll get
+                                       * ENOTCONN (and not EAGAIN, like we would for a normal connected
+                                       * socket that isn't writable at the moment). Since ENOTCONN on write()
+                                       * hence can mean two different things (i.e. connection not complete
+                                       * yet vs. already disconnected again), we store as a boolean whether
+                                       * we are still in connect(). */
+        }
+
+        varlink_set_state(v, VARLINK_IDLE_CLIENT);
+
+        *ret = TAKE_PTR(v);
+        return r;
+}
+
+int varlink_connect_fd(Varlink **ret, int fd) {
+        Varlink *v;
+        int r;
+
+        assert_return(ret, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        r = fd_nonblock(fd, true);
+        if (r < 0)
+                return r;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return r;
+
+        v->fd = fd;
+        varlink_set_state(v, VARLINK_IDLE_CLIENT);
+
+        /* Note that if this function is called we assume the passed socket (if it is one) is already
+         * properly connected, i.e. any asynchronous connect() done on it already completed. Because of that
+         * we'll not set the 'connecting' boolean here, i.e. we don't need to avoid write()ing to the socket
+         * until the connection is fully set up. Behaviour here is hence a bit different from
+         * varlink_connect_address() above, as there we do handle asynchronous connections ourselves and
+         * avoid doing write() on it before we saw EPOLLOUT for the first time. */
+
+        *ret = v;
+        return 0;
+}
+
+static void varlink_detach_event_sources(Varlink *v) {
+        assert(v);
+
+        v->io_event_source = sd_event_source_disable_unref(v->io_event_source);
+
+        v->time_event_source = sd_event_source_disable_unref(v->time_event_source);
+
+        v->quit_event_source = sd_event_source_disable_unref(v->quit_event_source);
+
+        v->defer_event_source = sd_event_source_disable_unref(v->defer_event_source);
+}
+
+static void varlink_clear(Varlink *v) {
+        assert(v);
+
+        varlink_detach_event_sources(v);
+
+        v->fd = safe_close(v->fd);
+
+        v->input_buffer = mfree(v->input_buffer);
+        v->output_buffer = mfree(v->output_buffer);
+
+        v->current = json_variant_unref(v->current);
+        v->reply = json_variant_unref(v->reply);
+
+        v->event = sd_event_unref(v->event);
+}
+
+static Varlink* varlink_destroy(Varlink *v) {
+        if (!v)
+                return NULL;
+
+        /* If this is called the server object must already been unreffed here. Why that? because when we
+         * linked up the varlink connection with the server object we took one ref in each direction */
+        assert(!v->server);
+
+        varlink_clear(v);
+
+        free(v->description);
+        return mfree(v);
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(Varlink, varlink, varlink_destroy);
+
+static int varlink_test_disconnect(Varlink *v) {
+        assert(v);
+
+        /* Tests whether we the the connection has been terminated. We are careful to not stop processing it
+         * prematurely, since we want to handle half-open connections as well as possible and want to flush
+         * out and read data before we close down if we can. */
+
+        /* Already disconnected? */
+        if (!VARLINK_STATE_IS_ALIVE(v->state))
+                return 0;
+
+        /* Wait until connection setup is complete, i.e. until asynchronous connect() completes */
+        if (v->connecting)
+                return 0;
+
+        /* Still something to write and we can write? Stay around */
+        if (v->output_buffer_size > 0 && !v->write_disconnected)
+                return 0;
+
+        /* Both sides gone already? Then there's no need to stick around */
+        if (v->read_disconnected && v->write_disconnected)
+                goto disconnect;
+
+        /* If we are waiting for incoming data but the read side is shut down, disconnect. */
+        if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) && v->read_disconnected)
+                goto disconnect;
+
+        /* Similar, if are a client that hasn't written anything yet but the write side is dead, also
+         * disconnect. We also explicitly check for POLLHUP here since we likely won't notice the write side
+         * being down if we never wrote anything. */
+        if (IN_SET(v->state, VARLINK_IDLE_CLIENT) && (v->write_disconnected || v->got_pollhup))
+                goto disconnect;
+
+        return 0;
+
+disconnect:
+        varlink_set_state(v, VARLINK_PENDING_DISCONNECT);
+        return 1;
+}
+
+static int varlink_write(Varlink *v) {
+        ssize_t n;
+
+        assert(v);
+
+        if (!VARLINK_STATE_IS_ALIVE(v->state))
+                return 0;
+        if (v->connecting) /* Writing while we are still wait for a non-blocking connect() to complete will
+                            * result in ENOTCONN, hence exit early here */
+                return 0;
+        if (v->output_buffer_size == 0)
+                return 0;
+        if (v->write_disconnected)
+                return 0;
+
+        assert(v->fd >= 0);
+
+        /* We generally prefer recv()/send() (mostly because of MSG_NOSIGNAL) but also want to be compatible
+         * with non-socket IO, hence fall back automatically */
+        if (!v->prefer_read_write) {
+                n = send(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size, MSG_DONTWAIT|MSG_NOSIGNAL);
+                if (n < 0 && errno == ENOTSOCK)
+                        v->prefer_read_write = true;
+        }
+        if (v->prefer_read_write)
+                n = write(v->fd, v->output_buffer + v->output_buffer_index, v->output_buffer_size);
+        if (n < 0) {
+                if (errno == EAGAIN)
+                        return 0;
+
+                if (ERRNO_IS_DISCONNECT(errno)) {
+                        /* If we get informed about a disconnect on write, then let's remember that, but not
+                         * act on it just yet. Let's wait for read() to report the issue first. */
+                        v->write_disconnected = true;
+                        return 1;
+                }
+
+                return -errno;
+        }
+
+        v->output_buffer_size -= n;
+
+        if (v->output_buffer_size == 0)
+                v->output_buffer_index = 0;
+        else
+                v->output_buffer_index += n;
+
+        v->timestamp = now(CLOCK_MONOTONIC);
+        return 1;
+}
+
+static int varlink_read(Varlink *v) {
+        size_t rs;
+        ssize_t n;
+
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER))
+                return 0;
+        if (v->connecting) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */
+                return 0;
+        if (v->current)
+                return 0;
+        if (v->input_buffer_unscanned > 0)
+                return 0;
+        if (v->read_disconnected)
+                return 0;
+
+        if (v->input_buffer_size >= VARLINK_BUFFER_MAX)
+                return -ENOBUFS;
+
+        assert(v->fd >= 0);
+
+        if (v->input_buffer_allocated <= v->input_buffer_index + v->input_buffer_size) {
+                size_t add;
+
+                add = MIN(VARLINK_BUFFER_MAX - v->input_buffer_size, VARLINK_READ_SIZE);
+
+                if (v->input_buffer_index == 0) {
+
+                        if (!GREEDY_REALLOC(v->input_buffer, v->input_buffer_allocated, v->input_buffer_size + add))
+                                return -ENOMEM;
+
+                } else {
+                        char *b;
+
+                        b = new(char, v->input_buffer_size + add);
+                        if (!b)
+                                return -ENOMEM;
+
+                        memcpy(b, v->input_buffer + v->input_buffer_index, v->input_buffer_size);
+
+                        free_and_replace(v->input_buffer, b);
+
+                        v->input_buffer_allocated = v->input_buffer_size + add;
+                        v->input_buffer_index = 0;
+                }
+        }
+
+        rs = v->input_buffer_allocated - (v->input_buffer_index + v->input_buffer_size);
+
+        if (!v->prefer_read_write) {
+                n = recv(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs, MSG_DONTWAIT);
+                if (n < 0 && errno == ENOTSOCK)
+                        v->prefer_read_write = true;
+        }
+        if (v->prefer_read_write)
+                n = read(v->fd, v->input_buffer + v->input_buffer_index + v->input_buffer_size, rs);
+        if (n < 0) {
+                if (errno == EAGAIN)
+                        return 0;
+
+                if (ERRNO_IS_DISCONNECT(errno)) {
+                        v->read_disconnected = true;
+                        return 1;
+                }
+
+                return -errno;
+        }
+        if (n == 0) { /* EOF */
+                v->read_disconnected = true;
+                return 1;
+        }
+
+        v->input_buffer_size += n;
+        v->input_buffer_unscanned += n;
+
+        return 1;
+}
+
+static int varlink_parse_message(Varlink *v) {
+        const char *e, *begin;
+        size_t sz;
+        int r;
+
+        assert(v);
+
+        if (v->current)
+                return 0;
+        if (v->input_buffer_unscanned <= 0)
+                return 0;
+
+        assert(v->input_buffer_unscanned <= v->input_buffer_size);
+        assert(v->input_buffer_index + v->input_buffer_size <= v->input_buffer_allocated);
+
+        begin = v->input_buffer + v->input_buffer_index;
+
+        e = memchr(begin + v->input_buffer_size - v->input_buffer_unscanned, 0, v->input_buffer_unscanned);
+        if (!e) {
+                v->input_buffer_unscanned = 0;
+                return 0;
+        }
+
+        sz = e - begin + 1;
+
+        varlink_log(v, "New incoming message: %s", begin);
+
+        r = json_parse(begin, &v->current, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        v->input_buffer_size -= sz;
+
+        if (v->input_buffer_size == 0)
+                v->input_buffer_index = 0;
+        else
+                v->input_buffer_index += sz;
+
+        v->input_buffer_unscanned = v->input_buffer_size;
+        return 1;
+}
+
+static int varlink_test_timeout(Varlink *v) {
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
+                return 0;
+        if (v->timeout == USEC_INFINITY)
+                return 0;
+
+        if (now(CLOCK_MONOTONIC) < usec_add(v->timestamp, v->timeout))
+                return 0;
+
+        varlink_set_state(v, VARLINK_PENDING_TIMEOUT);
+
+        return 1;
+}
+
+static int varlink_dispatch_local_error(Varlink *v, const char *error) {
+        int r;
+
+        assert(v);
+        assert(error);
+
+        if (!v->reply_callback)
+                return 0;
+
+        r = v->reply_callback(v, NULL, error, VARLINK_REPLY_ERROR|VARLINK_REPLY_LOCAL, v->userdata);
+        if (r < 0)
+                log_debug_errno(r, "Reply callback returned error, ignoring: %m");
+
+        return 1;
+}
+
+static int varlink_dispatch_timeout(Varlink *v) {
+        assert(v);
+
+        if (v->state != VARLINK_PENDING_TIMEOUT)
+                return 0;
+
+        varlink_set_state(v, VARLINK_PROCESSING_TIMEOUT);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_TIMEOUT);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_dispatch_disconnect(Varlink *v) {
+        assert(v);
+
+        if (v->state != VARLINK_PENDING_DISCONNECT)
+                return 0;
+
+        varlink_set_state(v, VARLINK_PROCESSING_DISCONNECT);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_DISCONNECTED);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_sanitize_parameters(JsonVariant **v) {
+        assert(v);
+
+        /* Varlink always wants a parameters list, hence make one if the caller doesn't want any */
+        if (!*v)
+                return json_variant_new_object(v, NULL, 0);
+        else if (!json_variant_is_object(*v))
+                return -EINVAL;
+
+        return 0;
+}
+
+static int varlink_dispatch_reply(Varlink *v) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        VarlinkReplyFlags flags = 0;
+        const char *error = NULL;
+        JsonVariant *e;
+        const char *k;
+        int r;
+
+        assert(v);
+
+        if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
+                return 0;
+        if (!v->current)
+                return 0;
+
+        assert(v->n_pending > 0);
+
+        if (!json_variant_is_object(v->current))
+                goto invalid;
+
+        JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) {
+
+                if (streq(k, "error")) {
+                        if (error)
+                                goto invalid;
+                        if (!json_variant_is_string(e))
+                                goto invalid;
+
+                        error = json_variant_string(e);
+                        flags |= VARLINK_REPLY_ERROR;
+
+                } else if (streq(k, "parameters")) {
+                        if (parameters)
+                                goto invalid;
+                        if (!json_variant_is_object(e))
+                                goto invalid;
+
+                        parameters = json_variant_ref(e);
+
+                } else if (streq(k, "continues")) {
+                        if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_REPLY_CONTINUES;
+                } else
+                        goto invalid;
+        }
+
+        if (error && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                goto invalid;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                goto invalid;
+
+        if (v->state == VARLINK_AWAITING_REPLY) {
+                varlink_set_state(v, VARLINK_PROCESSING_REPLY);
+
+                if (v->reply_callback) {
+                        r = v->reply_callback(v, parameters, error, flags, v->userdata);
+                        if (r < 0)
+                                log_debug_errno(r, "Reply callback returned error, ignoring: %m");
+                }
+
+                v->current = json_variant_unref(v->current);
+
+                if (v->state == VARLINK_PROCESSING_REPLY) {
+                        assert(v->n_pending > 0);
+                        v->n_pending--;
+
+                        varlink_set_state(v, v->n_pending == 0 ? VARLINK_IDLE_CLIENT : VARLINK_AWAITING_REPLY);
+                }
+        } else {
+                assert(v->state == VARLINK_CALLING);
+
+                if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
+                        goto invalid;
+
+                varlink_set_state(v, VARLINK_CALLED);
+        }
+
+        return 1;
+
+invalid:
+        varlink_set_state(v, VARLINK_PROCESSING_FAILURE);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL);
+        varlink_close(v);
+
+        return 1;
+}
+
+static int varlink_dispatch_method(Varlink *v) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        VarlinkMethodFlags flags = 0;
+        const char *method = NULL, *error;
+        JsonVariant *e;
+        VarlinkMethod callback;
+        const char *k;
+        int r;
+
+        assert(v);
+
+        if (v->state != VARLINK_IDLE_SERVER)
+                return 0;
+        if (!v->current)
+                return 0;
+
+        if (!json_variant_is_object(v->current))
+                goto invalid;
+
+        JSON_VARIANT_OBJECT_FOREACH(k, e, v->current) {
+
+                if (streq(k, "method")) {
+                        if (method)
+                                goto invalid;
+                        if (!json_variant_is_string(e))
+                                goto invalid;
+
+                        method = json_variant_string(e);
+
+                } else if (streq(k, "parameters")) {
+                        if (parameters)
+                                goto invalid;
+                        if (!json_variant_is_object(e))
+                                goto invalid;
+
+                        parameters = json_variant_ref(e);
+
+                } else if (streq(k, "oneway")) {
+
+                        if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0)
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_METHOD_ONEWAY;
+
+                } else if (streq(k, "more")) {
+
+                        if ((flags & (VARLINK_METHOD_ONEWAY|VARLINK_METHOD_MORE)) != 0)
+                                goto invalid;
+
+                        if (!json_variant_is_boolean(e))
+                                goto invalid;
+
+                        if (json_variant_boolean(e))
+                                flags |= VARLINK_METHOD_MORE;
+
+                } else
+                        goto invalid;
+        }
+
+        if (!method)
+                goto invalid;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                goto fail;
+
+        varlink_set_state(v, (flags & VARLINK_METHOD_MORE)   ? VARLINK_PROCESSING_METHOD_MORE :
+                             (flags & VARLINK_METHOD_ONEWAY) ? VARLINK_PROCESSING_METHOD_ONEWAY :
+                                                               VARLINK_PROCESSING_METHOD);
+
+        assert(v->server);
+
+        if (STR_IN_SET(method, "org.varlink.service.GetInfo", "org.varlink.service.GetInterface")) {
+                /* For now, we don't implement a single of varlink's own methods */
+                callback = NULL;
+                error = VARLINK_ERROR_METHOD_NOT_IMPLEMENTED;
+        } else if (startswith(method, "org.varlink.service.")) {
+                callback = NULL;
+                error = VARLINK_ERROR_METHOD_NOT_FOUND;
+        } else {
+                callback = hashmap_get(v->server->methods, method);
+                error = VARLINK_ERROR_METHOD_NOT_FOUND;
+        }
+
+        if (callback) {
+                r = callback(v, parameters, flags, v->userdata);
+                if (r < 0) {
+                        log_debug_errno(r, "Callback for %s returned error: %m", method);
+
+                        /* We got an error back from the callback. Propagate it to the client if the method call remains unanswered. */
+                        if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) {
+                                r = varlink_errorb(v, VARLINK_ERROR_SYSTEM, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("errno", JSON_BUILD_INTEGER(-r))));
+                                if (r < 0)
+                                        return r;
+                        }
+                }
+        } else if (!FLAGS_SET(flags, VARLINK_METHOD_ONEWAY)) {
+                assert(error);
+
+                r = varlink_errorb(v, error, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method))));
+                if (r < 0)
+                        return r;
+        }
+
+        switch (v->state) {
+
+        case VARLINK_PROCESSED_METHOD: /* Method call is fully processed */
+        case VARLINK_PROCESSING_METHOD_ONEWAY: /* ditto */
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+                break;
+
+        case VARLINK_PROCESSING_METHOD: /* Method call wasn't replied to, will be replied to later */
+                varlink_set_state(v, VARLINK_PENDING_METHOD);
+                break;
+
+        case VARLINK_PROCESSED_METHOD_MORE:  /* One reply for a "more" message was sent, more to come */
+        case VARLINK_PROCESSING_METHOD_MORE: /* No reply for a "more" message was sent, more to come */
+                varlink_set_state(v, VARLINK_PENDING_METHOD_MORE);
+                break;
+
+        default:
+                assert_not_reached("Unexpected state");
+
+        }
+
+        return r;
+
+invalid:
+        r = -EINVAL;
+
+fail:
+        varlink_set_state(v, VARLINK_PROCESSING_FAILURE);
+        varlink_dispatch_local_error(v, VARLINK_ERROR_PROTOCOL);
+        varlink_close(v);
+
+        return r;
+}
+
+int varlink_process(Varlink *v) {
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        varlink_ref(v);
+
+        r = varlink_write(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_reply(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_method(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_parse_message(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_read(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_test_disconnect(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_disconnect(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_test_timeout(v);
+        if (r != 0)
+                goto finish;
+
+        r = varlink_dispatch_timeout(v);
+        if (r != 0)
+                goto finish;
+
+finish:
+        if (r >= 0 && v->defer_event_source) {
+                int q;
+
+                /* If we did some processing, make sure we are called again soon */
+                q = sd_event_source_set_enabled(v->defer_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF);
+                if (q < 0)
+                        r = q;
+        }
+
+        if (r < 0) {
+                if (VARLINK_STATE_IS_ALIVE(v->state))
+                        /* Initiate disconnection */
+                        varlink_set_state(v, VARLINK_PENDING_DISCONNECT);
+                else
+                        /* We failed while disconnecting, in that case close right away */
+                        varlink_close(v);
+        }
+
+        varlink_unref(v);
+        return r;
+}
+
+static void handle_revents(Varlink *v, int revents) {
+        assert(v);
+
+        if (v->connecting) {
+                /* If we have seen POLLOUT or POLLHUP on a socket we are asynchronously waiting a connect()
+                 * to complete on, we know we are ready. We don't read the connection error here though,
+                 * we'll get the error on the next read() or write(). */
+                if ((revents & (POLLOUT|POLLHUP)) == 0)
+                        return;
+
+                varlink_log(v, "Anynchronous connection completed.");
+                v->connecting = false;
+        } else {
+                /* Note that we don't care much about POLLIN/POLLOUT here, we'll just try reading and writing
+                 * what we can. However, we do care about POLLHUP to detect connection termination even if we
+                 * momentarily don't want to read nor write anything. */
+
+                if (!FLAGS_SET(revents, POLLHUP))
+                        return;
+
+                varlink_log(v, "Got POLLHUP from socket.");
+                v->got_pollhup = true;
+        }
+}
+
+int varlink_wait(Varlink *v, usec_t timeout) {
+        struct timespec ts;
+        struct pollfd pfd;
+        int r, fd, events;
+        usec_t t;
+
+        assert_return(v, -EINVAL);
+        assert_return(!v->server, -ENOTTY);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        r = varlink_get_timeout(v, &t);
+        if (r < 0)
+                return r;
+        if (t != USEC_INFINITY) {
+                usec_t n;
+
+                n = now(CLOCK_MONOTONIC);
+                if (t < n)
+                        t = 0;
+                else
+                        t = usec_sub_unsigned(t, n);
+        }
+
+        if (timeout != USEC_INFINITY &&
+            (t == USEC_INFINITY || timeout < t))
+                t = timeout;
+
+        fd = varlink_get_fd(v);
+        if (fd < 0)
+                return fd;
+
+        events = varlink_get_events(v);
+        if (events < 0)
+                return events;
+
+        pfd = (struct pollfd) {
+                .fd = fd,
+                .events = events,
+        };
+
+        r = ppoll(&pfd, 1,
+                  t == USEC_INFINITY ? NULL : timespec_store(&ts, t),
+                  NULL);
+        if (r < 0)
+                return -errno;
+
+        handle_revents(v, pfd.revents);
+
+        return r > 0 ? 1 : 0;
+}
+
+int varlink_get_fd(Varlink *v) {
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (v->fd < 0)
+                return -EBADF;
+
+        return v->fd;
+}
+
+int varlink_get_events(Varlink *v) {
+        int ret = 0;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        if (v->connecting) /* When processing an asynchronous connect(), we only wait for EPOLLOUT, which
+                            * tells us that the connection is now complete. Before that we should neither
+                            * write() or read() from the fd. */
+                return EPOLLOUT;
+
+        if (!v->read_disconnected &&
+            IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) &&
+            !v->current &&
+            v->input_buffer_unscanned <= 0)
+                ret |= EPOLLIN;
+
+        if (!v->write_disconnected &&
+            v->output_buffer_size > 0)
+                ret |= EPOLLOUT;
+
+        return ret;
+}
+
+int varlink_get_timeout(Varlink *v, usec_t *ret) {
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING) &&
+            v->timeout != USEC_INFINITY) {
+                if (ret)
+                        *ret = usec_add(v->timestamp, v->timeout);
+                return 1;
+        } else {
+                if (ret)
+                        *ret = USEC_INFINITY;
+                return 0;
+        }
+}
+
+int varlink_flush(Varlink *v) {
+        int ret = 0, r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+
+        for (;;) {
+                struct pollfd pfd;
+
+                if (v->output_buffer_size == 0)
+                        break;
+                if (v->write_disconnected)
+                        return -ECONNRESET;
+
+                r = varlink_write(v);
+                if (r < 0)
+                        return r;
+                if (r > 0) {
+                        ret = 1;
+                        continue;
+                }
+
+                pfd = (struct pollfd) {
+                        .fd = v->fd,
+                        .events = POLLOUT,
+                };
+
+                if (poll(&pfd, 1, -1) < 0)
+                        return -errno;
+
+                handle_revents(v, pfd.revents);
+        }
+
+        return ret;
+}
+
+static void varlink_detach_server(Varlink *v) {
+        assert(v);
+
+        if (!v->server)
+                return;
+
+        if (v->server->by_uid &&
+            v->ucred_acquired &&
+            uid_is_valid(v->ucred.uid)) {
+                unsigned c;
+
+                c = PTR_TO_UINT(hashmap_get(v->server->by_uid, UID_TO_PTR(v->ucred.uid)));
+                assert(c > 0);
+
+                if (c == 1)
+                        (void) hashmap_remove(v->server->by_uid, UID_TO_PTR(v->ucred.uid));
+                else
+                        (void) hashmap_replace(v->server->by_uid, UID_TO_PTR(v->ucred.uid), UINT_TO_PTR(c - 1));
+        }
+
+        assert(v->server->n_connections > 0);
+        v->server->n_connections--;
+
+        /* If this is a connection associated to a server, then let's disconnect the server and the
+         * connection from each other. This drops the dangling reference that connect_callback() set up. */
+        v->server = varlink_server_unref(v->server);
+        varlink_unref(v);
+}
+
+int varlink_close(Varlink *v) {
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return 0;
+
+        varlink_set_state(v, VARLINK_DISCONNECTED);
+
+        /* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref
+         * which would destroy us before we can call varlink_clear() */
+        varlink_ref(v);
+        varlink_detach_server(v);
+        varlink_clear(v);
+        varlink_unref(v);
+
+        return 1;
+}
+
+Varlink* varlink_flush_close_unref(Varlink *v) {
+
+        if (!v)
+                return NULL;
+
+        (void) varlink_flush(v);
+        (void) varlink_close(v);
+
+        return varlink_unref(v);
+}
+
+static int varlink_enqueue_json(Varlink *v, JsonVariant *m) {
+        _cleanup_free_ char *text = NULL;
+        int r;
+
+        assert(v);
+        assert(m);
+
+        r = json_variant_format(m, 0, &text);
+        if (r < 0)
+                return r;
+
+        if (v->output_buffer_size + r + 1 > VARLINK_BUFFER_MAX)
+                return -ENOBUFS;
+
+        varlink_log(v, "Sending message: %s", text);
+
+        if (v->output_buffer_size == 0) {
+
+                free_and_replace(v->output_buffer, text);
+
+                v->output_buffer_size = v->output_buffer_allocated = r + 1;
+                v->output_buffer_index = 0;
+
+        } else if (v->output_buffer_index == 0) {
+
+                if (!GREEDY_REALLOC(v->output_buffer, v->output_buffer_allocated, v->output_buffer_size + r + 1))
+                        return -ENOMEM;
+
+                memcpy(v->output_buffer + v->output_buffer_size, text, r + 1);
+                v->output_buffer_size += r + 1;
+
+        } else {
+                char *n;
+                const size_t new_size = v->output_buffer_size + r + 1;
+
+                n = new(char, new_size);
+                if (!n)
+                        return -ENOMEM;
+
+                memcpy(mempcpy(n, v->output_buffer + v->output_buffer_index, v->output_buffer_size), text, r + 1);
+
+                free_and_replace(v->output_buffer, n);
+                v->output_buffer_allocated = v->output_buffer_size = new_size;
+                v->output_buffer_index = 0;
+        }
+
+        return 0;
+}
+
+int varlink_send(Varlink *v, const char *method, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)),
+                                       JSON_BUILD_PAIR("oneway", JSON_BUILD_BOOLEAN(true))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        /* No state change here, this is one-way only after all */
+        v->timestamp = now(CLOCK_MONOTONIC);
+        return 0;
+}
+
+int varlink_sendb(Varlink *v, const char *method, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, method);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_send(v, method, parameters);
+}
+
+int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        varlink_set_state(v, VARLINK_AWAITING_REPLY);
+        v->n_pending++;
+        v->timestamp = now(CLOCK_MONOTONIC);
+
+        return 0;
+}
+
+int varlink_invokeb(Varlink *v, const char *method, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, method);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_invoke(v, method, parameters);
+}
+
+int varlink_call(
+                Varlink *v,
+                const char *method,
+                JsonVariant *parameters,
+                JsonVariant **ret_parameters,
+                const char **ret_error_id,
+                VarlinkReplyFlags *ret_flags) {
+
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(method, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_IDLE_CLIENT))
+                return -EBUSY;
+
+        assert(v->n_pending == 0); /* n_pending can't be > 0 if we are in VARLINK_IDLE_CLIENT state */
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        varlink_set_state(v, VARLINK_CALLING);
+        v->n_pending++;
+        v->timestamp = now(CLOCK_MONOTONIC);
+
+        while (v->state == VARLINK_CALLING) {
+
+                r = varlink_process(v);
+                if (r < 0)
+                        return r;
+                if (r > 0)
+                        continue;
+
+                r = varlink_wait(v, USEC_INFINITY);
+                if (r < 0)
+                        return r;
+        }
+
+        switch (v->state) {
+
+        case VARLINK_CALLED:
+                assert(v->current);
+
+                json_variant_unref(v->reply);
+                v->reply = TAKE_PTR(v->current);
+
+                varlink_set_state(v, VARLINK_IDLE_CLIENT);
+                assert(v->n_pending == 1);
+                v->n_pending--;
+
+                if (ret_parameters)
+                        *ret_parameters = json_variant_by_key(v->reply, "parameters");
+                if (ret_error_id)
+                        *ret_error_id = json_variant_string(json_variant_by_key(v->reply, "error"));
+                if (ret_flags)
+                        *ret_flags = 0;
+
+                return 1;
+
+        case VARLINK_PENDING_DISCONNECT:
+        case VARLINK_DISCONNECTED:
+                return -ECONNRESET;
+
+        case VARLINK_PENDING_TIMEOUT:
+                return -ETIME;
+
+        default:
+                assert_not_reached("Unexpected state after method call.");
+        }
+}
+
+int varlink_callb(
+                Varlink *v,
+                const char *method,
+                JsonVariant **ret_parameters,
+                const char **ret_error_id,
+                VarlinkReplyFlags *ret_flags, ...) {
+
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, ret_flags);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_call(v, method, parameters, ret_parameters, ret_error_id, ret_flags);
+}
+
+int varlink_reply(Varlink *v, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state,
+                    VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE,
+                    VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) {
+                /* We just replied to a method call that was let hanging for a while (i.e. we were outside of
+                 * the varlink_dispatch_method() stack frame), which means with this reply we are ready to
+                 * process further messages. */
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+        } else
+                /* We replied to a method call from within the varlink_dispatch_method() stack frame), which
+                 * means we should it handle the rest of the state engine. */
+                varlink_set_state(v, VARLINK_PROCESSED_METHOD);
+
+        return 1;
+}
+
+int varlink_replyb(Varlink *v, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, v);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_reply(v, parameters);
+}
+
+int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(error_id, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state,
+                    VARLINK_PROCESSING_METHOD, VARLINK_PROCESSING_METHOD_MORE,
+                    VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("error", JSON_BUILD_STRING(error_id)),
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        if (IN_SET(v->state, VARLINK_PENDING_METHOD, VARLINK_PENDING_METHOD_MORE)) {
+                v->current = json_variant_unref(v->current);
+                varlink_set_state(v, VARLINK_IDLE_SERVER);
+        } else
+                varlink_set_state(v, VARLINK_PROCESSED_METHOD);
+
+        return 1;
+}
+
+int varlink_errorb(Varlink *v, const char *error_id, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(error_id, -EINVAL);
+
+        va_start(ap, error_id);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_error(v, error_id, parameters);
+}
+
+int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters) {
+
+        assert_return(v, -EINVAL);
+        assert_return(parameters, -EINVAL);
+
+        /* We expect to be called in one of two ways: the 'parameters' argument is a string variant in which
+         * case it is the parameter key name that is invalid. Or the 'parameters' argument is an object
+         * variant in which case we'll pull out the first key. The latter mode is useful in functions that
+         * don't expect any arguments. */
+
+        if (json_variant_is_string(parameters))
+                return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER, parameters);
+
+        if (json_variant_is_object(parameters) &&
+            json_variant_elements(parameters) > 0)
+                return varlink_error(v, VARLINK_ERROR_INVALID_PARAMETER,
+                                     json_variant_by_index(parameters, 0));
+
+        return -EINVAL;
+}
+
+int varlink_notify(Varlink *v, JsonVariant *parameters) {
+        _cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        if (v->state == VARLINK_DISCONNECTED)
+                return -ENOTCONN;
+        if (!IN_SET(v->state, VARLINK_PROCESSING_METHOD_MORE, VARLINK_PENDING_METHOD_MORE))
+                return -EBUSY;
+
+        r = varlink_sanitize_parameters(&parameters);
+        if (r < 0)
+                return r;
+
+        r = json_build(&m, JSON_BUILD_OBJECT(
+                                       JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)),
+                                       JSON_BUILD_PAIR("continues", JSON_BUILD_BOOLEAN(true))));
+        if (r < 0)
+                return r;
+
+        r = varlink_enqueue_json(v, m);
+        if (r < 0)
+                return r;
+
+        /* No state change, as more is coming */
+        return 1;
+}
+
+int varlink_notifyb(Varlink *v, ...) {
+        _cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
+        va_list ap;
+        int r;
+
+        assert_return(v, -EINVAL);
+
+        va_start(ap, v);
+        r = json_buildv(&parameters, ap);
+        va_end(ap);
+
+        if (r < 0)
+                return r;
+
+        return varlink_notify(v, parameters);
+}
+
+int varlink_bind_reply(Varlink *v, VarlinkReply callback) {
+        assert_return(v, -EINVAL);
+
+        if (callback && v->reply_callback && callback != v->reply_callback)
+                return -EBUSY;
+
+        v->reply_callback = callback;
+
+        return 0;
+}
+
+void* varlink_set_userdata(Varlink *v, void *userdata) {
+        void *old;
+
+        assert_return(v, NULL);
+
+        old = v->userdata;
+        v->userdata = userdata;
+
+        return old;
+}
+
+void* varlink_get_userdata(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->userdata;
+}
+
+static int varlink_acquire_ucred(Varlink *v) {
+        int r;
+
+        assert(v);
+
+        if (v->ucred_acquired)
+                return 0;
+
+        r = getpeercred(v->fd, &v->ucred);
+        if (r < 0)
+                return r;
+
+        v->ucred_acquired = true;
+        return 0;
+}
+
+int varlink_get_peer_uid(Varlink *v, uid_t *ret) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = varlink_acquire_ucred(v);
+        if (r < 0)
+                return r;
+
+        if (!uid_is_valid(v->ucred.uid))
+                return -ENODATA;
+
+        *ret = v->ucred.uid;
+        return 0;
+}
+
+int varlink_get_peer_pid(Varlink *v, pid_t *ret) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        r = varlink_acquire_ucred(v);
+        if (r < 0)
+                return r;
+
+        if (!pid_is_valid(v->ucred.pid))
+                return -ENODATA;
+
+        *ret = v->ucred.pid;
+        return 0;
+}
+
+int varlink_set_relative_timeout(Varlink *v, usec_t timeout) {
+        assert_return(v, -EINVAL);
+        assert_return(timeout > 0, -EINVAL);
+
+        v->timeout = timeout;
+        return 0;
+}
+
+VarlinkServer *varlink_get_server(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->server;
+}
+
+int varlink_set_description(Varlink *v, const char *description) {
+        assert_return(v, -EINVAL);
+
+        return free_and_strdup(&v->description, description);
+}
+
+static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        handle_revents(v, revents);
+        (void) varlink_process(v);
+
+        return 1;
+}
+
+static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        (void) varlink_process(v);
+        return 1;
+}
+
+static int defer_callback(sd_event_source *s, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(s);
+        assert(v);
+
+        (void) varlink_process(v);
+        return 1;
+}
+
+static int prepare_callback(sd_event_source *s, void *userdata) {
+        Varlink *v = userdata;
+        int r, e;
+        usec_t until;
+
+        assert(s);
+        assert(v);
+
+        e = varlink_get_events(v);
+        if (e < 0)
+                return e;
+
+        r = sd_event_source_set_io_events(v->io_event_source, e);
+        if (r < 0)
+                return r;
+
+        r = varlink_get_timeout(v, &until);
+        if (r < 0)
+                return r;
+        if (r > 0) {
+                r = sd_event_source_set_time(v->time_event_source, until);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_event_source_set_enabled(v->time_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF);
+        if (r < 0)
+                return r;
+
+        return 1;
+}
+
+static int quit_callback(sd_event_source *event, void *userdata) {
+        Varlink *v = userdata;
+
+        assert(event);
+        assert(v);
+
+        varlink_flush(v);
+        varlink_close(v);
+
+        return 1;
+}
+
+int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority) {
+        int r;
+
+        assert_return(v, -EINVAL);
+        assert_return(!v->event, -EBUSY);
+
+        if (e)
+                v->event = sd_event_ref(e);
+        else {
+                r = sd_event_default(&v->event);
+                if (r < 0)
+                        return r;
+        }
+
+        r = sd_event_add_time(v->event, &v->time_event_source, CLOCK_MONOTONIC, 0, 0, time_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->time_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->time_event_source, "varlink-time");
+
+        r = sd_event_add_exit(v->event, &v->quit_event_source, quit_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->quit_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->quit_event_source, "varlink-quit");
+
+        r = sd_event_add_io(v->event, &v->io_event_source, v->fd, 0, io_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_prepare(v->io_event_source, prepare_callback);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->io_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->io_event_source, "varlink-io");
+
+        r = sd_event_add_defer(v->event, &v->defer_event_source, defer_callback, v);
+        if (r < 0)
+                goto fail;
+
+        r = sd_event_source_set_priority(v->defer_event_source, priority);
+        if (r < 0)
+                goto fail;
+
+        (void) sd_event_source_set_description(v->defer_event_source, "varlink-defer");
+
+        return 0;
+
+fail:
+        varlink_detach_event(v);
+        return r;
+}
+
+
+void varlink_detach_event(Varlink *v) {
+        if (!v)
+                return;
+
+        varlink_detach_event_sources(v);
+
+        v->event = sd_event_unref(v->event);
+}
+
+sd_event *varlink_get_event(Varlink *v) {
+        assert_return(v, NULL);
+
+        return v->event;
+}
+
+int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags) {
+        VarlinkServer *s;
+
+        assert_return(ret, -EINVAL);
+        assert_return((flags & ~_VARLINK_SERVER_FLAGS_ALL) == 0, -EINVAL);
+
+        s = new(VarlinkServer, 1);
+        if (!s)
+                return -ENOMEM;
+
+        *s = (VarlinkServer) {
+                .n_ref = 1,
+                .flags = flags,
+                .connections_max = varlink_server_connections_max(NULL),
+                .connections_per_uid_max = varlink_server_connections_per_uid_max(NULL),
+        };
+
+        *ret = s;
+        return 0;
+}
+
+static VarlinkServer* varlink_server_destroy(VarlinkServer *s) {
+        char *m;
+
+        if (!s)
+                return NULL;
+
+        varlink_server_shutdown(s);
+
+        while ((m = hashmap_steal_first_key(s->methods)))
+                free(m);
+
+        hashmap_free(s->methods);
+        hashmap_free(s->by_uid);
+
+        sd_event_unref(s->event);
+
+        free(s->description);
+
+        return mfree(s);
+}
+
+DEFINE_TRIVIAL_REF_UNREF_FUNC(VarlinkServer, varlink_server, varlink_server_destroy);
+
+static int validate_connection(VarlinkServer *server, const struct ucred *ucred) {
+        int allowed = -1;
+
+        assert(server);
+        assert(ucred);
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ROOT_ONLY))
+                allowed = ucred->uid == 0;
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_MYSELF_ONLY))
+                allowed = allowed > 0 || ucred->uid == getuid();
+
+        if (allowed == 0) { /* Allow access when it is explicitly allowed or when neither
+                             * VARLINK_SERVER_ROOT_ONLY nor VARLINK_SERVER_MYSELF_ONLY are specified. */
+                varlink_server_log(server, "Unprivileged client attempted connection, refusing.");
+                return 0;
+        }
+
+        if (server->n_connections >= server->connections_max) {
+                varlink_server_log(server, "Connection limit of %u reached, refusing.", server->connections_max);
+                return 0;
+        }
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) {
+                unsigned c;
+
+                if (!uid_is_valid(ucred->uid)) {
+                        varlink_server_log(server, "Client with invalid UID attempted connection, refusing.");
+                        return 0;
+                }
+
+                c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
+                if (c >= server->connections_per_uid_max) {
+                        varlink_server_log(server, "Per-UID connection limit of %u reached, refusing.",
+                                           server->connections_per_uid_max);
+                        return 0;
+                }
+        }
+
+        return 1;
+}
+
+static int count_connection(VarlinkServer *server, struct ucred *ucred) {
+        unsigned c;
+        int r;
+
+        assert(server);
+        assert(ucred);
+
+        server->n_connections++;
+
+        if (FLAGS_SET(server->flags, VARLINK_SERVER_ACCOUNT_UID)) {
+                r = hashmap_ensure_allocated(&server->by_uid, NULL);
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to allocate UID hash table: %m");
+
+                c = PTR_TO_UINT(hashmap_get(server->by_uid, UID_TO_PTR(ucred->uid)));
+
+                varlink_server_log(server, "Connections of user " UID_FMT ": %u (of %u max)",
+                                   ucred->uid, c, server->connections_per_uid_max);
+
+                r = hashmap_replace(server->by_uid, UID_TO_PTR(ucred->uid), UINT_TO_PTR(c + 1));
+                if (r < 0)
+                        return log_debug_errno(r, "Failed to increment counter in UID hash table: %m");
+        }
+
+        return 0;
+}
+
+int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) {
+        _cleanup_(varlink_unrefp) Varlink *v = NULL;
+        bool ucred_acquired;
+        struct ucred ucred;
+        int r;
+
+        assert_return(server, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        if ((server->flags & (VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_ACCOUNT_UID)) != 0) {
+                r = getpeercred(fd, &ucred);
+                if (r < 0)
+                        return varlink_server_log_errno(server, r, "Failed to acquire peer credentials of incoming socket, refusing: %m");
+
+                ucred_acquired = true;
+
+                r = validate_connection(server, &ucred);
+                if (r < 0)
+                        return r;
+                if (r == 0)
+                        return -EPERM;
+        } else
+                ucred_acquired = false;
+
+        r = varlink_new(&v);
+        if (r < 0)
+                return varlink_server_log_errno(server, r, "Failed to allocate connection object: %m");
+
+        r = count_connection(server, &ucred);
+        if (r < 0)
+                return r;
+
+        v->fd = fd;
+        v->userdata = server->userdata;
+        if (ucred_acquired) {
+                v->ucred = ucred;
+                v->ucred_acquired = true;
+        }
+
+        (void) asprintf(&v->description, "%s-%i", server->description ?: "varlink", v->fd);
+
+        /* Link up the server and the connection, and take reference in both directions. Note that the
+         * reference on the connection is left dangling. It will be dropped when the connection is closed,
+         * which happens in varlink_close(), including in the event loop quit callback. */
+        v->server = varlink_server_ref(server);
+        varlink_ref(v);
+
+        varlink_set_state(v, VARLINK_IDLE_SERVER);
+
+        r = varlink_attach_event(v, server->event, server->event_priority);
+        if (r < 0) {
+                varlink_log_errno(v, r, "Failed to attach new connection: %m");
+                v->fd = -1; /* take the fd out of the connection again */
+                varlink_close(v);
+                return r;
+        }
+
+        if (ret)
+                *ret = v;
+
+        return 0;
+}
+
+static int connect_callback(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
+        VarlinkServerSocket *ss = userdata;
+        _cleanup_close_ int cfd = -1;
+        Varlink *v = NULL;
+        int r;
+
+        assert(source);
+        assert(ss);
+
+        varlink_server_log(ss->server, "New incoming connection.");
+
+        cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
+        if (cfd < 0) {
+                if (ERRNO_IS_ACCEPT_AGAIN(errno))
+                        return 0;
+
+                return varlink_server_log_errno(ss->server, errno, "Failed to accept incoming socket: %m");
+        }
+
+        r = varlink_server_add_connection(ss->server, cfd, &v);
+        if (r < 0)
+                return 0;
+
+        TAKE_FD(cfd);
+
+        if (ss->server->connect_callback) {
+                r = ss->server->connect_callback(ss->server, v, ss->server->userdata);
+                if (r < 0) {
+                        varlink_log_errno(v, r, "Connection callback returned error, disconnecting client: %m");
+                        varlink_close(v);
+                        return 0;
+                }
+        }
+
+        return 0;
+}
+
+int varlink_server_listen_fd(VarlinkServer *s, int fd) {
+        _cleanup_free_ VarlinkServerSocket *ss = NULL;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(fd >= 0, -EBADF);
+
+        r = fd_nonblock(fd, true);
+        if (r < 0)
+                return r;
+
+        ss = new(VarlinkServerSocket, 1);
+        if (!ss)
+                return -ENOMEM;
+
+        *ss = (VarlinkServerSocket) {
+                .server = s,
+                .fd = fd,
+        };
+
+        if (s->event) {
+                _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
+
+                r = sd_event_add_io(s->event, &es, fd, EPOLLIN, connect_callback, ss);
+                if (r < 0)
+                        return r;
+
+                r = sd_event_source_set_priority(ss->event_source, s->event_priority);
+                if (r < 0)
+                        return r;
+        }
+
+        LIST_PREPEND(sockets, s->sockets, TAKE_PTR(ss));
+        return 0;
+}
+
+int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t m) {
+        union sockaddr_union sockaddr;
+        _cleanup_close_ int fd = -1;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(address, -EINVAL);
+        assert_return((m & ~0777) == 0, -EINVAL);
+
+        r = sockaddr_un_set_path(&sockaddr.un, address);
+        if (r < 0)
+                return r;
+
+        fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+        if (fd < 0)
+                return -errno;
+
+        (void) sockaddr_un_unlink(&sockaddr.un);
+
+        RUN_WITH_UMASK(~m & 0777)
+                if (bind(fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0)
+                        return -errno;
+
+        if (listen(fd, SOMAXCONN) < 0)
+                return -errno;
+
+        r = varlink_server_listen_fd(s, fd);
+        if (r < 0)
+                return r;
+
+        TAKE_FD(fd);
+        return 0;
+}
+
+void* varlink_server_set_userdata(VarlinkServer *s, void *userdata) {
+        void *ret;
+
+        assert_return(s, NULL);
+
+        ret = s->userdata;
+        s->userdata = userdata;
+
+        return ret;
+}
+
+void* varlink_server_get_userdata(VarlinkServer *s) {
+        assert_return(s, NULL);
+
+        return s->userdata;
+}
+
+static VarlinkServerSocket* varlink_server_socket_destroy(VarlinkServerSocket *ss) {
+        if (!ss)
+                return NULL;
+
+        if (ss->server)
+                LIST_REMOVE(sockets, ss->server->sockets, ss);
+
+        sd_event_source_disable_unref(ss->event_source);
+
+        free(ss->address);
+        safe_close(ss->fd);
+
+        return mfree(ss);
+}
+
+int varlink_server_shutdown(VarlinkServer *s) {
+        assert_return(s, -EINVAL);
+
+        while (s->sockets)
+                varlink_server_socket_destroy(s->sockets);
+
+        return 0;
+}
+
+int varlink_server_attach_event(VarlinkServer *s, sd_event *e, int64_t priority) {
+        VarlinkServerSocket *ss;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(!s->event, -EBUSY);
+
+        if (e)
+                s->event = sd_event_ref(e);
+        else {
+                r = sd_event_default(&s->event);
+                if (r < 0)
+                        return r;
+        }
+
+        LIST_FOREACH(sockets, ss, s->sockets) {
+                assert(!ss->event_source);
+
+                r = sd_event_add_io(s->event, &ss->event_source, ss->fd, EPOLLIN, connect_callback, ss);
+                if (r < 0)
+                        goto fail;
+
+                r = sd_event_source_set_priority(ss->event_source, priority);
+                if (r < 0)
+                        goto fail;
+        }
+
+        s->event_priority = priority;
+        return 0;
+
+fail:
+        varlink_server_detach_event(s);
+        return r;
+}
+
+int varlink_server_detach_event(VarlinkServer *s) {
+        VarlinkServerSocket *ss;
+
+        assert_return(s, -EINVAL);
+
+        LIST_FOREACH(sockets, ss, s->sockets) {
+
+                if (!ss->event_source)
+                        continue;
+
+                (void) sd_event_source_set_enabled(ss->event_source, SD_EVENT_OFF);
+                ss->event_source = sd_event_source_unref(ss->event_source);
+        }
+
+        sd_event_unref(s->event);
+        return 0;
+}
+
+sd_event *varlink_server_get_event(VarlinkServer *s) {
+        assert_return(s, NULL);
+
+        return s->event;
+}
+
+int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback) {
+        char *m;
+        int r;
+
+        assert_return(s, -EINVAL);
+        assert_return(method, -EINVAL);
+        assert_return(callback, -EINVAL);
+
+        if (startswith(method, "org.varlink.service."))
+                return -EEXIST;
+
+        r = hashmap_ensure_allocated(&s->methods, &string_hash_ops);
+        if (r < 0)
+                return r;
+
+        m = strdup(method);
+        if (!m)
+                return -ENOMEM;
+
+        r = hashmap_put(s->methods, m, callback);
+        if (r < 0) {
+                free(m);
+                return r;
+        }
+
+        return 0;
+}
+
+int varlink_server_bind_method_many_internal(VarlinkServer *s, ...) {
+        va_list ap;
+        int r;
+
+        assert_return(s, -EINVAL);
+
+        va_start(ap, s);
+        for (;;) {
+                VarlinkMethod callback;
+                const char *method;
+
+                method = va_arg(ap, const char *);
+                if (!method)
+                        break;
+
+                callback = va_arg(ap, VarlinkMethod);
+
+                r = varlink_server_bind_method(s, method, callback);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
+int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect callback) {
+        assert_return(s, -EINVAL);
+
+        if (callback && s->connect_callback && callback != s->connect_callback)
+                return -EBUSY;
+
+        s->connect_callback = callback;
+        return 0;
+}
+
+unsigned varlink_server_connections_max(VarlinkServer *s) {
+        struct rlimit rl;
+
+        /* If a server is specified, return the setting for that server, otherwise the default value */
+        if (s)
+                return s->connections_max;
+
+        assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
+
+        /* Make sure we never use up more than Â¾th of RLIMIT_NOFILE for IPC */
+        if (VARLINK_DEFAULT_CONNECTIONS_MAX > rl.rlim_cur / 4 * 3)
+                return rl.rlim_cur / 4 * 3;
+
+        return VARLINK_DEFAULT_CONNECTIONS_MAX;
+}
+
+unsigned varlink_server_connections_per_uid_max(VarlinkServer *s) {
+        unsigned m;
+
+        if (s)
+                return s->connections_per_uid_max;
+
+        /* Make sure to never use up more than Â¾th of available connections for a single user */
+        m = varlink_server_connections_max(NULL);
+        if (VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX > m)
+                return m / 4 * 3;
+
+        return VARLINK_DEFAULT_CONNECTIONS_PER_UID_MAX;
+}
+
+int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m) {
+        assert_return(s, -EINVAL);
+        assert_return(m > 0, -EINVAL);
+
+        s->connections_per_uid_max = m;
+        return 0;
+}
+
+int varlink_server_set_connections_max(VarlinkServer *s, unsigned m) {
+        assert_return(s, -EINVAL);
+        assert_return(m > 0, -EINVAL);
+
+        s->connections_max = m;
+        return 0;
+}
+
+int varlink_server_set_description(VarlinkServer *s, const char *description) {
+        assert_return(s, -EINVAL);
+
+        return free_and_strdup(&s->description, description);
+}
diff --git a/src/shared/varlink.h b/src/shared/varlink.h
new file mode 100644 (file)
index 0000000..d96fa93
--- /dev/null
@@ -0,0 +1,162 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+#pragma once
+
+#include "sd-event.h"
+
+#include "json.h"
+#include "time-util.h"
+
+/* A minimal Varlink implementation. We only implement the minimal, obvious bits here though. No validation,
+ * no introspection, no name service, just the stuff actually needed.
+ *
+ * You might wonder why we aren't using libvarlink here? Varlink is a very simple protocol, which allows us
+ * to write our own implementation relatively easily. However, the main reasons are these:
+ *
+ * â€¢ We want to use our own JSON subsystem, with all the benefits that brings (i.e. accurate unsigned+signed
+ *   64bit integers, full fuzzing, logging during parsing and so on). If we'd want to use that with
+ *   libvarlink we'd have to serialize and deserialize all the time from its own representation which is
+ *   inefficient and nasty.
+ *
+ * â€¢ We want integration into sd-event, but also synchronous event-loop-less operation
+ *
+ * â€¢ We need proper per-UID accounting and access control, since we want to allow communication between
+ *   unprivileged clients and privileged servers.
+ *
+ * â€¢ And of course, we don't want the name service and introspection stuff for now (though that might
+ *   change).
+ */
+
+typedef struct Varlink Varlink;
+typedef struct VarlinkServer VarlinkServer;
+
+typedef enum VarlinkReplyFlags {
+        VARLINK_REPLY_ERROR     = 1 << 0,
+        VARLINK_REPLY_CONTINUES = 1 << 1,
+        VARLINK_REPLY_LOCAL     = 1 << 2,
+} VarlinkReplyFlags;
+
+typedef enum VarlinkMethodFlags {
+        VARLINK_METHOD_ONEWAY = 1 << 0,
+        VARLINK_METHOD_MORE   = 2 << 1,
+} VarlinkMethodFlags;
+
+typedef enum VarlinkServerFlags {
+        VARLINK_SERVER_ROOT_ONLY   = 1 << 0, /* Only accessible by root */
+        VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
+        VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
+
+        _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1,
+} VarlinkServerFlags;
+
+typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
+typedef int (*VarlinkReply)(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata);
+typedef int (*VarlinkConnect)(VarlinkServer *server, Varlink *link, void *userdata);
+
+int varlink_connect_address(Varlink **ret, const char *address);
+int varlink_connect_fd(Varlink **ret, int fd);
+
+Varlink* varlink_ref(Varlink *link);
+Varlink* varlink_unref(Varlink *v);
+
+int varlink_get_fd(Varlink *v);
+int varlink_get_events(Varlink *v);
+int varlink_get_timeout(Varlink *v, usec_t *ret);
+
+int varlink_attach_event(Varlink *v, sd_event *e, int64_t priority);
+void varlink_detach_event(Varlink *v);
+sd_event *varlink_get_event(Varlink *v);
+
+int varlink_process(Varlink *v);
+int varlink_wait(Varlink *v, usec_t timeout);
+
+int varlink_flush(Varlink *v);
+int varlink_close(Varlink *v);
+
+Varlink* varlink_flush_close_unref(Varlink *v);
+
+/* Enqueue method call, not expecting a reply */
+int varlink_send(Varlink *v, const char *method, JsonVariant *parameters);
+int varlink_sendb(Varlink *v, const char *method, ...);
+
+/* Send method call and wait for reply */
+int varlink_call(Varlink *v, const char *method, JsonVariant *parameters, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags);
+int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters, const char **ret_error_id, VarlinkReplyFlags *ret_flags, ...);
+
+/* Enqueue method call, expect a reply, which is eventually delivered to the reply callback */
+int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
+int varlink_invokeb(Varlink *v, const char *method, ...);
+
+/* Enqueue a final reply */
+int varlink_reply(Varlink *v, JsonVariant *parameters);
+int varlink_replyb(Varlink *v, ...);
+
+/* Enqueue a (final) error */
+int varlink_error(Varlink *v, const char *error_id, JsonVariant *parameters);
+int varlink_errorb(Varlink *v, const char *error_id, ...);
+int varlink_error_invalid_parameter(Varlink *v, JsonVariant *parameters);
+
+/* Enqueue a "more" reply */
+int varlink_notify(Varlink *v, JsonVariant *parameters);
+int varlink_notifyb(Varlink *v, ...);
+
+/* Bind a disconnect, reply or timeout callback */
+int varlink_bind_reply(Varlink *v, VarlinkReply reply);
+
+void* varlink_set_userdata(Varlink *v, void *userdata);
+void* varlink_get_userdata(Varlink *v);
+
+int varlink_get_peer_uid(Varlink *v, uid_t *ret);
+int varlink_get_peer_pid(Varlink *v, pid_t *ret);
+
+int varlink_set_relative_timeout(Varlink *v, usec_t usec);
+
+VarlinkServer* varlink_get_server(Varlink *v);
+
+int varlink_set_description(Varlink *v, const char *d);
+
+/* Create a varlink server */
+int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
+VarlinkServer *varlink_server_ref(VarlinkServer *s);
+VarlinkServer *varlink_server_unref(VarlinkServer *s);
+
+/* Add addresses or fds to listen on */
+int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t mode);
+int varlink_server_listen_fd(VarlinkServer *s, int fd);
+int varlink_server_add_connection(VarlinkServer *s, int fd, Varlink **ret);
+
+/* Bind callbacks */
+int varlink_server_bind_method(VarlinkServer *s, const char *method, VarlinkMethod callback);
+int varlink_server_bind_method_many_internal(VarlinkServer *s, ...);
+#define varlink_server_bind_method_many(s, ...) varlink_server_bind_method_many_internal(s, __VA_ARGS__, NULL)
+int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect connect);
+
+void* varlink_server_set_userdata(VarlinkServer *s, void *userdata);
+void* varlink_server_get_userdata(VarlinkServer *s);
+
+int varlink_server_attach_event(VarlinkServer *v, sd_event *e, int64_t priority);
+int varlink_server_detach_event(VarlinkServer *v);
+sd_event *varlink_server_get_event(VarlinkServer *v);
+
+int varlink_server_shutdown(VarlinkServer *server);
+
+unsigned varlink_server_connections_max(VarlinkServer *s);
+unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);
+
+int varlink_server_set_connections_per_uid_max(VarlinkServer *s, unsigned m);
+int varlink_server_set_connections_max(VarlinkServer *s, unsigned m);
+
+int varlink_server_set_description(VarlinkServer *s, const char *description);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(Varlink *, varlink_flush_close_unref);
+DEFINE_TRIVIAL_CLEANUP_FUNC(VarlinkServer *, varlink_server_unref);
+
+#define VARLINK_ERROR_DISCONNECTED "io.systemd.Disconnected"
+#define VARLINK_ERROR_TIMEOUT "io.systemd.TimedOut"
+#define VARLINK_ERROR_PROTOCOL "io.systemd.Protocol"
+#define VARLINK_ERROR_SYSTEM "io.systemd.System"
+
+#define VARLINK_ERROR_INTERFACE_NOT_FOUND "org.varlink.service.InterfaceNotFound"
+#define VARLINK_ERROR_METHOD_NOT_FOUND "org.varlink.service.MethodNotFound"
+#define VARLINK_ERROR_METHOD_NOT_IMPLEMENTED "org.varlink.service.MethodNotImplemented"
+#define VARLINK_ERROR_INVALID_PARAMETER "org.varlink.service.InvalidParameter"
index 35b2c2aa463bb62b18de938d3e0679c6245719dd..9623fe9ea29f3cf06b57ab357507c19c9e101988 100644 (file)
@@ -212,7 +212,7 @@ static int sync_making_progress(unsigned long long *prev_dirty) {
 }
 
 static void sync_with_progress(void) {
-        unsigned long long dirty = ULONG_LONG_MAX;
+        unsigned long long dirty = ULLONG_MAX;
         unsigned checks;
         pid_t pid;
         int r;
index 11aabaf923d2391d284cfe9460bb92d1ab0ec2e6..ed570deaee09ba0f097eb8e42ce939151fecbf69 100644 (file)
@@ -50,7 +50,7 @@ static int write_hibernate_location_info(void) {
         if (streq(type, "partition")) {
                 r = write_string_file("/sys/power/resume", device, WRITE_STRING_FILE_DISABLE_BUFFER);
                 if (r < 0)
-                        return log_debug_errno(r, "Faileed to write partitoin device to /sys/power/resume: %m");
+                        return log_debug_errno(r, "Failed to write partition device to /sys/power/resume: %m");
 
                 return r;
         }
index d9b57e2c734ceb27e47989e79d988e440f9910f0..ab62368e9cee0cee1e0d55a0f0e856259b2165ef 100644 (file)
@@ -38,6 +38,7 @@ enum {
         SD_DHCP_CLIENT_EVENT_IP_CHANGE          = 2,
         SD_DHCP_CLIENT_EVENT_EXPIRED            = 3,
         SD_DHCP_CLIENT_EVENT_RENEW              = 4,
+        SD_DHCP_CLIENT_EVENT_SELECTING          = 5,
 };
 
 enum {
@@ -98,7 +99,7 @@ enum {
 
 typedef struct sd_dhcp_client sd_dhcp_client;
 
-typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
+typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
 int sd_dhcp_client_set_callback(
                 sd_dhcp_client *client,
                 sd_dhcp_client_callback_t cb,
@@ -175,6 +176,7 @@ int sd_dhcp_client_get_lease(
 
 int sd_dhcp_client_stop(sd_dhcp_client *client);
 int sd_dhcp_client_start(sd_dhcp_client *client);
+int sd_dhcp_client_send_release(sd_dhcp_client *client);
 
 sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
 sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
index 7bb8609376c43e6f42d6b1c1bcb2050ac0ff4a26..b14c92697b44803ad2d26d0409ff849de0d71684 100644 (file)
@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
 
 sd_event_source* sd_event_source_ref(sd_event_source *s);
 sd_event_source* sd_event_source_unref(sd_event_source *s);
+sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
 
 sd_event *sd_event_source_get_event(sd_event_source *s);
 void* sd_event_source_get_userdata(sd_event_source *s);
@@ -149,6 +150,7 @@ int sd_event_source_set_floating(sd_event_source *s, int b);
 /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
 _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
+_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
 
 _SD_END_DECLARATIONS;
 
index d327b27308b68d56e139cf619ce698f7ccf9f4df..d27e0ad2019cb9b5016404ab1e24d3c360777e3b 100644 (file)
 ***/
 
 #include <inttypes.h>
-#include <linux/neighbour.h>
-#include <linux/rtnetlink.h>
 #include <net/ethernet.h>
 #include <netinet/ether.h>
 #include <netinet/in.h>
+#include <linux/neighbour.h>
+#include <linux/rtnetlink.h>
 
 #include "sd-event.h"
 
index e878d874afb2b923a4a65b0462d40775a50b4111..ee6cdb6d54b1ce83b74ce302da3e3f5647ffec04 100644 (file)
@@ -595,6 +595,10 @@ tests += [
           libmount,
           libblkid]],
 
+        [['src/test/test-varlink.c'],
+         [],
+         [threads]],
+
         [['src/test/test-cgroup-util.c'],
          [],
          []],
index 2dfdfe35ec740bb34643a5f78a49a4aa628ba6a5..e6b6d96d5a91b393ba4b2e2de80535d0e76b542e 100644 (file)
@@ -6,6 +6,7 @@
 #include "alloc-util.h"
 #include "macro.h"
 #include "memory-util.h"
+#include "tests.h"
 
 static void test_alloca(void) {
         static const uint8_t zero[997] = { };
@@ -106,11 +107,39 @@ static void test_bool_assign(void) {
         assert(!h);
 }
 
+static int cleanup_counter = 0;
+
+static void cleanup1(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup2(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+static void cleanup3(void *a) {
+        log_info("%s(%p)", __func__, a);
+        assert_se(++cleanup_counter == *(int*) a);
+}
+
+static void test_cleanup_order(void) {
+        _cleanup_(cleanup1) int x1 = 4, x2 = 3;
+        _cleanup_(cleanup3) int z = 2;
+        _cleanup_(cleanup2) int y = 1;
+        log_debug("x1: %p", &x1);
+        log_debug("x2: %p", &x2);
+        log_debug("y: %p", &y);
+        log_debug("z: %p", &z);
+}
+
 int main(int argc, char *argv[]) {
+        test_setup_logging(LOG_DEBUG);
+
         test_alloca();
         test_GREEDY_REALLOC();
         test_memdup_multiply_and_greedy_realloc();
         test_bool_assign();
+        test_cleanup_order();
 
         return 0;
 }
index 96d92279fbfef4ebffaa34246be45b676d164e45..0e563f54970b8e5734d8d4eae4b703a1bd7bd553 100644 (file)
@@ -75,12 +75,45 @@ static void test_getttyname_malloc(void) {
         assert_se(PATH_IN_SET(ttyname, "ptmx", "pts/ptmx"));
 }
 
+static void test_one_color(const char *name, const char *color) {
+        printf("<%s%s%s>\n", color, name, ansi_normal());
+}
+
+static void test_colors(void) {
+        log_info("/* %s */", __func__);
+
+        test_one_color("normal", ansi_normal());
+        test_one_color("highlight", ansi_highlight());
+        test_one_color("red", ansi_red());
+        test_one_color("green", ansi_green());
+        test_one_color("yellow", ansi_yellow());
+        test_one_color("blue", ansi_blue());
+        test_one_color("megenta", ansi_magenta());
+        test_one_color("grey", ansi_grey());
+        test_one_color("highlight-red", ansi_highlight_red());
+        test_one_color("highlight-green", ansi_highlight_green());
+        test_one_color("highlight-yellow", ansi_highlight_yellow());
+        test_one_color("highlight-blue", ansi_highlight_blue());
+        test_one_color("highlight-magenta", ansi_highlight_magenta());
+        test_one_color("highlight-grey", ansi_highlight_grey());
+
+        test_one_color("underline", ansi_underline());
+        test_one_color("highlight-underline", ansi_highlight_underline());
+        test_one_color("highlight-red-underline", ansi_highlight_red_underline());
+        test_one_color("highlight-green-underline", ansi_highlight_green_underline());
+        test_one_color("highlight-yellow-underline", ansi_highlight_yellow_underline());
+        test_one_color("highlight-blue-underline", ansi_highlight_blue_underline());
+        test_one_color("highlight-magenta-underline", ansi_highlight_magenta_underline());
+        test_one_color("highlight-grey-underline", ansi_highlight_grey_underline());
+}
+
 int main(int argc, char *argv[]) {
         test_setup_logging(LOG_INFO);
 
         test_default_term_for_tty();
         test_read_one_char();
         test_getttyname_malloc();
+        test_colors();
 
         return 0;
 }
diff --git a/src/test/test-varlink.c b/src/test/test-varlink.c
new file mode 100644 (file)
index 0000000..fbfc72c
--- /dev/null
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <fcntl.h>
+#include <poll.h>
+#include <pthread.h>
+
+#include "sd-event.h"
+
+#include "fd-util.h"
+#include "json.h"
+#include "rm-rf.h"
+#include "strv.h"
+#include "tmpfile-util.h"
+#include "user-util.h"
+#include "varlink.h"
+
+/* Let's pick some high value, that is higher than the largest listen() backlog, but leaves enough room below
+   the typical RLIMIT_NOFILE value of 1024 so that we can process both sides of each socket in our
+   process. Or in other words: "OVERLOAD_CONNECTIONS * 2 + x < 1024" should hold, for some small x that
+   should cover any auxiliary fds, the listener server fds, stdin/stdout/stderr and whatever else. */
+#define OVERLOAD_CONNECTIONS 333
+
+static int n_done = 0;
+static int block_write_fd = -1;
+
+static int method_something(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+        _cleanup_(json_variant_unrefp) JsonVariant *ret = NULL;
+        JsonVariant *a, *b;
+        intmax_t x, y;
+        int r;
+
+        a = json_variant_by_key(parameters, "a");
+        if (!a)
+                return varlink_error(link, "io.test.BadParameters", NULL);
+
+        x = json_variant_integer(a);
+
+        b = json_variant_by_key(parameters, "b");
+        if (!b)
+                return varlink_error(link, "io.test.BadParameters", NULL);
+
+        y = json_variant_integer(b);
+
+        r = json_build(&ret, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("sum", JSON_BUILD_INTEGER(x + y))));
+        if (r < 0)
+                return r;
+
+        return varlink_reply(link, ret);
+}
+
+static int method_done(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
+
+        if (++n_done == 2)
+                sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+        return 0;
+}
+
+static int reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+        JsonVariant *sum;
+
+        sum = json_variant_by_key(parameters, "sum");
+
+        assert_se(json_variant_integer(sum) == 7+22);
+
+        if (++n_done == 2)
+                sd_event_exit(varlink_get_event(link), EXIT_FAILURE);
+
+        return 0;
+}
+
+static int on_connect(VarlinkServer *s, Varlink *link, void *userdata) {
+        uid_t uid = UID_INVALID;
+
+        assert(s);
+        assert(link);
+
+        assert_se(varlink_get_peer_uid(link, &uid) >= 0);
+        assert_se(getuid() == uid);
+
+        return 0;
+}
+
+static int overload_reply(Varlink *link, JsonVariant *parameters, const char *error_id, VarlinkReplyFlags flags, void *userdata) {
+
+        /* This method call reply should always be called with a disconnection, since the method call should
+         * be talking to an overloaded server */
+
+        log_debug("Over reply triggered with error: %s", strna(error_id));
+        assert_se(streq(error_id, VARLINK_ERROR_DISCONNECTED));
+        sd_event_exit(varlink_get_event(link), 0);
+
+        return 0;
+}
+
+static void flood_test(const char *address) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_free_ Varlink **connections = NULL;
+        size_t k;
+        char x = 'x';
+
+        log_debug("Flooding server...");
+
+        /* Block the main event loop while we flood */
+        assert_se(write(block_write_fd, &x, sizeof(x)) == sizeof(x));
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        /* Flood the server with connections */
+        assert_se(connections = new0(Varlink*, OVERLOAD_CONNECTIONS));
+        for (k = 0; k < OVERLOAD_CONNECTIONS; k++) {
+                _cleanup_free_ char *t = NULL;
+                log_debug("connection %zu", k);
+                assert_se(varlink_connect_address(connections + k, address) >= 0);
+
+                assert_se(asprintf(&t, "flood-%zu", k) >= 0);
+                assert_se(varlink_set_description(connections[k], t) >= 0);
+                assert_se(varlink_attach_event(connections[k], e, k) >= 0);
+                assert_se(varlink_sendb(connections[k], "io.test.Rubbish", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("id", JSON_BUILD_INTEGER(k)))) >= 0);
+        }
+
+        /* Then, create one more, which should fail */
+        log_debug("Creating overload connection...");
+        assert_se(varlink_connect_address(&c, address) >= 0);
+        assert_se(varlink_set_description(c, "overload-client") >= 0);
+        assert_se(varlink_attach_event(c, e, k) >= 0);
+        assert_se(varlink_bind_reply(c, overload_reply) >= 0);
+        assert_se(varlink_invokeb(c, "io.test.Overload", JSON_BUILD_OBJECT(JSON_BUILD_PAIR("foo", JSON_BUILD_STRING("bar")))) >= 0);
+
+        /* Unblock it */
+        log_debug("Unblocking server...");
+        block_write_fd = safe_close(block_write_fd);
+
+        /* This loop will terminate as soon as the overload reply callback is called */
+        assert_se(sd_event_loop(e) >= 0);
+
+        /* And close all connections again */
+        for (k = 0; k < OVERLOAD_CONNECTIONS; k++)
+                connections[k] = varlink_unref(connections[k]);
+}
+
+static void *thread(void *arg) {
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *i = NULL;
+        JsonVariant *o = NULL;
+        const char *e;
+
+        assert_se(json_build(&i, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(88)),
+                                                   JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(99)))) >= 0);
+
+        assert_se(varlink_connect_address(&c, arg) >= 0);
+        assert_se(varlink_set_description(c, "thread-client") >= 0);
+
+        assert_se(varlink_call(c, "io.test.DoSomething", i, &o, &e, NULL) >= 0);
+        assert_se(json_variant_integer(json_variant_by_key(o, "sum")) == 88 + 99);
+        assert_se(!e);
+
+        assert_se(varlink_callb(c, "io.test.IDontExist", &o, &e, NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("x", JSON_BUILD_REAL(5.5)))) >= 0);
+        assert_se(streq_ptr(json_variant_string(json_variant_by_key(o, "method")), "io.test.IDontExist"));
+        assert_se(streq(e, VARLINK_ERROR_METHOD_NOT_FOUND));
+
+        flood_test(arg);
+
+        assert_se(varlink_send(c, "io.test.Done", NULL) >= 0);
+
+        return NULL;
+}
+
+static int block_fd_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+        char c;
+
+        assert_se(fd_nonblock(fd, false) >= 0);
+
+        assert_se(read(fd, &c, sizeof(c)) == sizeof(c));
+        /* When a character is written to this pipe we'll block until the pipe is closed. */
+
+        assert_se(read(fd, &c, sizeof(c)) == 0);
+
+        assert_se(fd_nonblock(fd, true) >= 0);
+
+        assert_se(sd_event_source_set_enabled(s, SD_EVENT_OFF) >= 0);
+
+        return 0;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_(sd_event_source_unrefp) sd_event_source *block_event = NULL;
+        _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
+        _cleanup_(varlink_flush_close_unrefp) Varlink *c = NULL;
+        _cleanup_(rm_rf_physical_and_freep) char *tmpdir = NULL;
+        _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+        _cleanup_(sd_event_unrefp) sd_event *e = NULL;
+        _cleanup_(close_pairp) int block_fds[2] = { -1, -1 };
+        pthread_t t;
+        const char *sp;
+
+        log_set_max_level(LOG_DEBUG);
+        log_open();
+
+        assert_se(mkdtemp_malloc("/tmp/varlink-test-XXXXXX", &tmpdir) >= 0);
+        sp = strjoina(tmpdir, "/socket");
+
+        assert_se(sd_event_default(&e) >= 0);
+
+        assert_se(pipe2(block_fds, O_NONBLOCK|O_CLOEXEC) >= 0);
+        assert_se(sd_event_add_io(e, &block_event, block_fds[0], EPOLLIN, block_fd_handler, NULL) >= 0);
+        assert_se(sd_event_source_set_priority(block_event, SD_EVENT_PRIORITY_IMPORTANT) >= 0);
+        block_write_fd = TAKE_FD(block_fds[1]);
+
+        assert_se(varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID) >= 0);
+        assert_se(varlink_server_set_description(s, "our-server") >= 0);
+
+        assert_se(varlink_server_bind_method(s, "io.test.DoSomething", method_something) >= 0);
+        assert_se(varlink_server_bind_method(s, "io.test.Done", method_done) >= 0);
+        assert_se(varlink_server_bind_connect(s, on_connect) >= 0);
+        assert_se(varlink_server_listen_address(s, sp, 0600) >= 0);
+        assert_se(varlink_server_attach_event(s, e, 0) >= 0);
+        assert_se(varlink_server_set_connections_max(s, OVERLOAD_CONNECTIONS) >= 0);
+
+        assert_se(varlink_connect_address(&c, sp) >= 0);
+        assert_se(varlink_set_description(c, "main-client") >= 0);
+        assert_se(varlink_bind_reply(c, reply) >= 0);
+
+        assert_se(json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("a", JSON_BUILD_INTEGER(7)),
+                                                   JSON_BUILD_PAIR("b", JSON_BUILD_INTEGER(22)))) >= 0);
+
+        assert_se(varlink_invoke(c, "io.test.DoSomething", v) >= 0);
+
+        assert_se(varlink_attach_event(c, e, 0) >= 0);
+
+        assert_se(pthread_create(&t, NULL, thread, (void*) sp) == 0);
+
+        assert_se(sd_event_loop(e) >= 0);
+
+        assert_se(pthread_join(t, NULL) == 0);
+
+        return 0;
+}
index 324b8e679c8d8516049d72f6620d1f1ae7191a8e..4061eec99e7cdf8b8ba54ccf15d4302d387c4f59 100644 (file)
@@ -25,15 +25,16 @@ typedef enum NamingSchemeFlags {
         NAMING_SR_IOV_V        = 1 << 0, /* Use "v" suffix for SR-IOV, see 609948c7043a40008b8299529c978ed8e11de8f6*/
         NAMING_NPAR_ARI        = 1 << 1, /* Use NPAR "ARI", see 6bc04997b6eab35d1cb9fa73889892702c27be09 */
         NAMING_INFINIBAND      = 1 << 2, /* Use "ib" prefix for infiniband, see 938d30aa98df887797c9e05074a562ddacdcdf5e */
-        NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Allow zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
+        NAMING_ZERO_ACPI_INDEX = 1 << 3, /* Use zero acpi_index field, see d81186ef4f6a888a70f20a1e73a812d6acb9e22f */
         NAMING_ALLOW_RERENAMES = 1 << 4, /* Allow re-renaming of devices, see #9006 */
-        NAMING_NETDEVSIM       = 1 << 5, /* Allow re-renaming of netdevsim devices */
+        NAMING_NETDEVSIM       = 1 << 5, /* Generate names for netdevsim devices, see eaa9d507d85509c8bf727356e3884ec54b0fc646 */
+        NAMING_LABEL_NOPREFIX  = 1 << 6, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */
 
         /* And now the masks that combine the features above */
         NAMING_V238 = 0,
         NAMING_V239 = NAMING_V238 | NAMING_SR_IOV_V | NAMING_NPAR_ARI,
         NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES,
-        NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM,
+        NAMING_V243 = NAMING_V240 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX,
 
         _NAMING_SCHEME_FLAGS_INVALID = -1,
 } NamingSchemeFlags;
index 2c7dcf7d2a10ae877ac741813e19deafd717bb6f..c487bc00df23b24606b7eb0615b8d09edd1d2c9d 100644 (file)
@@ -9,86 +9,7 @@
  *
  * http://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames
  *
- * Two character prefixes based on the type of interface:
- *   en â€” Ethernet
- *   ib â€” InfiniBand
- *   sl â€” serial line IP (slip)
- *   wl â€” wlan
- *   ww â€” wwan
- *
- * Type of names:
- *   b<number>                             â€” BCMA bus core number
- *   c<bus_id>                             â€” bus id of a grouped CCW or CCW device,
- *                                           with all leading zeros stripped [s390]
- *   o<index>[n<phys_port_name>|d<dev_port>]
- *                                         â€” on-board device index number
- *   s<slot>[f<function>][n<phys_port_name>|d<dev_port>]
- *                                         â€” hotplug slot index number
- *   x<MAC>                                â€” MAC address
- *   [P<domain>]p<bus>s<slot>[f<function>][n<phys_port_name>|d<dev_port>]
- *                                         â€” PCI geographical location
- *   [P<domain>]p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>]
- *                                         â€” USB port number chain
- *   v<slot>                               - VIO slot number (IBM PowerVM)
- *   a<vendor><model>i<instance>           â€” Platform bus ACPI instance id
- *   i<addr>n<phys_port_name>             â€” Netdevsim bus address and port name
- *
- * All multi-function PCI devices will carry the [f<function>] number in the
- * device name, including the function 0 device.
- *
- * SR-IOV virtual devices are named based on the name of the parent interface,
- * with a suffix of "v<N>", where <N> is the virtual device number.
- *
- * When using PCI geography, The PCI domain is only prepended when it is not 0.
- *
- * For USB devices the full chain of port numbers of hubs is composed. If the
- * name gets longer than the maximum number of 15 characters, the name is not
- * exported.
- * The usual USB configuration == 1 and interface == 0 values are suppressed.
- *
- * PCI Ethernet card with firmware index "1":
- *   ID_NET_NAME_ONBOARD=eno1
- *   ID_NET_NAME_ONBOARD_LABEL=Ethernet Port 1
- *
- * PCI Ethernet card in hotplug slot with firmware index number:
- *   /sys/devices/pci0000:00/0000:00:1c.3/0000:05:00.0/net/ens1
- *   ID_NET_NAME_MAC=enx000000000466
- *   ID_NET_NAME_PATH=enp5s0
- *   ID_NET_NAME_SLOT=ens1
- *
- * PCI Ethernet multi-function card with 2 ports:
- *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.0/net/enp2s0f0
- *   ID_NET_NAME_MAC=enx78e7d1ea46da
- *   ID_NET_NAME_PATH=enp2s0f0
- *   /sys/devices/pci0000:00/0000:00:1c.0/0000:02:00.1/net/enp2s0f1
- *   ID_NET_NAME_MAC=enx78e7d1ea46dc
- *   ID_NET_NAME_PATH=enp2s0f1
- *
- * PCI wlan card:
- *   /sys/devices/pci0000:00/0000:00:1c.1/0000:03:00.0/net/wlp3s0
- *   ID_NET_NAME_MAC=wlx0024d7e31130
- *   ID_NET_NAME_PATH=wlp3s0
- *
- * PCI IB host adapter with 2 ports:
- *   /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.0/net/ibp21s0f0
- *   ID_NET_NAME_PATH=ibp21s0f0
- *   /sys/devices/pci0000:00/0000:00:03.0/0000:15:00.1/net/ibp21s0f1
- *   ID_NET_NAME_PATH=ibp21s0f1
- *
- * USB built-in 3G modem:
- *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.6/net/wwp0s29u1u4i6
- *   ID_NET_NAME_MAC=wwx028037ec0200
- *   ID_NET_NAME_PATH=wwp0s29u1u4i6
- *
- * USB Android phone:
- *   /sys/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/net/enp0s29u1u2
- *   ID_NET_NAME_MAC=enxd626b3450fb5
- *   ID_NET_NAME_PATH=enp0s29u1u2
- *
- * s390 grouped CCW interface:
- *  /sys/devices/css0/0.0.0007/0.0.f5f0/group_device/net/encf5f0
- *  ID_NET_NAME_MAC=enx026d3c00000a
- *  ID_NET_NAME_PATH=encf5f0
+ * When the code here is changed, man/systemd.net-naming-scheme.xml must be updated too.
  */
 
 #include <errno.h>
@@ -249,7 +170,7 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         char *s;
         int r;
 
-        /* ACPI _DSM  â€” device specific method for naming a PCI or PCI Express device */
+        /* ACPI _DSM â€” device specific method for naming a PCI or PCI Express device */
         if (sd_device_get_sysattr_value(names->pcidev, "acpi_index", &attr) < 0) {
                 /* SMBIOS type 41 â€” Onboard Devices Extended Information */
                 r = sd_device_get_sysattr_value(names->pcidev, "index", &attr);
@@ -263,10 +184,11 @@ static int dev_pci_onboard(sd_device *dev, struct netnames *names) {
         if (idx == 0 && !naming_scheme_has(NAMING_ZERO_ACPI_INDEX))
                 return -EINVAL;
 
-        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to report for
-         * example). Let's define a cut-off where we don't consider the index reliable anymore. We pick some arbitrary
-         * cut-off, which is somewhere beyond the realistic number of physical network interface a system might
-         * have. Ideally the kernel would already filter his crap for us, but it doesn't currently. */
+        /* Some BIOSes report rubbish indexes that are excessively high (2^24-1 is an index VMware likes to
+         * report for example). Let's define a cut-off where we don't consider the index reliable anymore. We
+         * pick some arbitrary cut-off, which is somewhere beyond the realistic number of physical network
+         * interface a system might have. Ideally the kernel would already filter his crap for us, but it
+         * doesn't currently. */
         if (idx > ONBOARD_INDEX_MAX)
                 return -ENOENT;
 
@@ -722,9 +644,8 @@ static int names_ccw(sd_device *dev, struct netnames *names) {
         if (r < 0)
                 return r;
 
-        /* Check the length of the bus-ID.  Rely on that the kernel provides
-         * a correct bus-ID; alternatively, improve this check and parse and
-         * verify each bus-ID part...
+        /* Check the length of the bus-ID. Rely on the fact that the kernel provides a correct bus-ID;
+         * alternatively, improve this check and parse and verify each bus-ID part...
          */
         bus_id_len = strlen(bus_id);
         if (!IN_SET(bus_id_len, 8, 9))
@@ -960,7 +881,9 @@ static int builtin_net_id(sd_device *dev, int argc, char *argv[], bool test) {
                         udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str);
 
                 if (names.pci_onboard_label &&
-                    snprintf_ok(str, sizeof str, "%s%s", prefix, names.pci_onboard_label))
+                    snprintf_ok(str, sizeof str, "%s%s",
+                                naming_scheme_has(NAMING_LABEL_NOPREFIX) ? "" : prefix,
+                                names.pci_onboard_label))
                         udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str);
 
                 if (names.pci_path[0] &&
index cab1b5ac0c56aa5524e035435ac797eba7096421..a0a7ac0f9e01a0c2b2d5569c04dc116a4fb73df2 100644 (file)
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/wait.h>
 #include <unistd.h>
 
 #include "sd-event.h"
index a6f7ee82bbfebf447d3251c073f6b4383a365bed..873d03bc5e51232d3cda5ea285465b8e6259fce5 100644 (file)
@@ -69,6 +69,8 @@
 #include "udev.h"
 #include "user-util.h"
 
+#define WORKER_NUM_MAX 2048U
+
 static bool arg_debug = false;
 static int arg_daemonize = false;
 static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY;
@@ -1745,16 +1747,18 @@ static int run(int argc, char *argv[]) {
                 return r;
 
         if (arg_children_max == 0) {
+                unsigned long cpu_limit, mem_limit;
+                unsigned long cpu_count = 1;
                 cpu_set_t cpu_set;
-                unsigned long mem_limit;
-
-                arg_children_max = 8;
 
                 if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0)
-                        arg_children_max += CPU_COUNT(&cpu_set) * 8;
+                        cpu_count = CPU_COUNT(&cpu_set);
+
+                cpu_limit = cpu_count * 2 + 16;
+                mem_limit = MAX(physical_memory() / (128UL*1024*1024), 10U);
 
-                mem_limit = physical_memory() / (128LU*1024*1024);
-                arg_children_max = MAX(10U, MIN(arg_children_max, mem_limit));
+                arg_children_max = MIN(cpu_limit, mem_limit);
+                arg_children_max = MIN(WORKER_NUM_MAX, arg_children_max);
 
                 log_debug("Set children_max to %u", arg_children_max);
         }
index 976dd825bcb213b28bd3880546076de12f396541..d2bc3921d281deeb1ce262298355af74325c84f4 100644 (file)
@@ -70,29 +70,19 @@ static int verify_vc_allocation_byfd(int fd) {
         return verify_vc_allocation(vcs.v_active);
 }
 
-static int verify_vc_kbmode(int fd) {
-        int curr_mode;
-
-        /*
-         * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
-         * Otherwise we would (likely) interfere with X11's processing of the
-         * key events.
-         *
-         * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
-         */
-
-        if (ioctl(fd, KDGKBMODE, &curr_mode) < 0)
-                return -errno;
-
-        return IN_SET(curr_mode, K_XLATE, K_UNICODE) ? 0 : -EBUSY;
-}
-
 static int toggle_utf8(const char *name, int fd, bool utf8) {
         int r;
         struct termios tc = {};
 
         assert(name);
 
+        r = vt_verify_kbmode(fd);
+        if (r == -EBUSY) {
+                log_warning_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", name);
+                return 0;
+        } else if (r < 0)
+                return log_warning_errno(r, "Failed to verify kbdmode on %s: %m", name);
+
         r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE);
         if (r < 0)
                 return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode on %s: %m", enable_disable(utf8), name);
@@ -290,7 +280,7 @@ static void setup_remaining_vcs(int src_fd, unsigned src_idx, bool utf8) {
                         continue;
                 }
 
-                if (verify_vc_kbmode(fd_d) < 0)
+                if (vt_verify_kbmode(fd_d) < 0)
                         continue;
 
                 toggle_utf8(ttyname, fd_d, utf8);
@@ -365,7 +355,7 @@ static int find_source_vc(char **ret_path, unsigned *ret_idx) {
                                 err = -fd;
                         continue;
                 }
-                r = verify_vc_kbmode(fd);
+                r = vt_verify_kbmode(fd);
                 if (r < 0) {
                         if (!err)
                                 err = -r;
@@ -398,7 +388,7 @@ static int verify_source_vc(char **ret_path, const char *src_vc) {
         if (r < 0)
                 return log_error_errno(r, "Virtual console %s is not allocated: %m", src_vc);
 
-        r = verify_vc_kbmode(fd);
+        r = vt_verify_kbmode(fd);
         if (r < 0)
                 return log_error_errno(r, "Virtual console %s is not in K_XLATE or K_UNICODE: %m", src_vc);
 
index ace2302589f486d4febc2259dfab078c4b635148..27084f62424bf2cf3407c7a1a6bcc6bed2aa15b9 100644 (file)
@@ -40,7 +40,3 @@ fs.protected_symlinks = 1
 # Enable regular file and FIFO protection
 fs.protected_regular = 1
 fs.protected_fifos = 1
-
-# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
-# of 2^16), to make PID collisions less likely.
-kernel.pid_max = 4194304
diff --git a/sysctl.d/50-pid-max.conf b/sysctl.d/50-pid-max.conf
new file mode 100644 (file)
index 0000000..1eff2d7
--- /dev/null
@@ -0,0 +1,16 @@
+#  This file is part of systemd.
+#
+#  systemd is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU Lesser General Public License as published by
+#  the Free Software Foundation; either version 2.1 of the License, or
+#  (at your option) any later version.
+
+# See sysctl.d(5) and core(5) for documentation.
+
+# To override settings in this file, create a local file in /etc
+# (e.g. /etc/sysctl.d/90-override.conf), and put any assignments
+# there.
+
+# Bump the numeric PID range to its maximum of 2^22 (from the in-kernel default
+# of 2^16), to make PID collisions less likely.
+kernel.pid_max = 4194304
index 64f6ce942edd6bd6f8c9f61aaeaca0744265ba44..3f072e3db77cd85af37a7cec9d04f1c41024eee8 100644 (file)
@@ -6,6 +6,13 @@ install_data(
 
 in_files = []
 
+# Kernel determines PID_MAX_LIMIT by
+# #define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
+#         (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
+if cc.sizeof('long') > 4
+        install_data('50-pid-max.conf', install_dir : sysctldir)
+endif
+
 if conf.get('ENABLE_COREDUMP') == 1
         in_files += ['50-coredump.conf']
 endif
similarity index 92%
rename from test/TEST-31-OOMPOLICY/test.sh
rename to test/TEST-32-OOMPOLICY/test.sh
index 55752e6a701d84060044c968568d6ffd67a28df9..7e9431dd11df8951a168957c427340ca5c906f12 100755 (executable)
@@ -1,6 +1,4 @@
 #!/bin/bash
-# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
-# ex: ts=8 sw=4 sts=4 et filetype=sh
 set -e
 TEST_DESCRIPTION="test OOM killer logic"
 TEST_NO_NSPAWN=1
similarity index 91%
rename from test/TEST-31-OOMPOLICY/testsuite.sh
rename to test/TEST-32-OOMPOLICY/testsuite.sh
index f0b1470d42e69df08a8eac78f79599ebbf05cb46..8aab487c6e7fb4708a45a5cf752fddcc99658bd5 100755 (executable)
@@ -1,6 +1,4 @@
 #!/bin/bash
-# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
-# ex: ts=8 sw=4 sts=4 et filetype=sh
 set -ex
 set -o pipefail
 
index f2189e1ccf2594cbede71df524fff3d14c7c6652..d2e10c71bd1a92adedc6f82bbad892be0ac26043 100644 (file)
@@ -32,6 +32,7 @@ FlowLabel=
 UDP6ZeroChecksumRx=
 Remote=
 UDP6ZeroCheckSumRx=
+IPDoNotFragment=
 [Bridge]
 ForwardDelaySec=
 HelloTimeSec=
@@ -139,7 +140,10 @@ DynamicTransmitLoadBalancing=
 [FooOverUDP]
 Protocol=
 Port=
+PeerPort=
 Encapsulation=
+Local=
+Peer=
 [Tap]
 MultiQueue=
 OneQueue=
@@ -150,6 +154,9 @@ VNetHeader=
 [IPVLAN]
 Mode=
 Flags=
+[IPVTAP]
+Mode=
+Flags=
 [Tun]
 OneQueue=
 MultiQueue=
index 9296c16c498df2f0606b036b6b47c540458ff5be..bba8948d35271dcc0a8a3ed1f8d19f9722fc07c6 100644 (file)
@@ -10,6 +10,9 @@ MulticastToUnicast=
 MulticastFlood=
 NeighborSuppression=
 Learning=
+ProxyARP=
+ProxyARPWiFi=
+MulticastRouter=
 [Match]
 KernelVersion=
 Type=
@@ -34,6 +37,7 @@ VLANId=
 MACAddress=
 Destination=
 VNI=
+AssociatedWith=
 [DHCP]
 UseDomains=
 UseRoutes=
@@ -59,6 +63,8 @@ ClientIdentifier=
 ListenPort=
 UseTimezone=
 RouteTable=
+BlackList=
+SendRelease=
 [Route]
 Destination=
 Protocol=
@@ -74,14 +80,17 @@ PreferredSource=
 Scope=
 MTUBytes=
 QuickAck=
+FastOpenNoCookie=
 Source=
 Metric=
+TTLPropagate=
 [Network]
 IPv6DuplicateAddressDetection=
 IPMasquerade=
 ProxyARP=
 PrimarySlave=
 IPv4LLRoute=
+DefaultRouteOnDevice=
 Address=
 IPv6ProxyNDPAddress=
 IPv6AcceptRA=
@@ -96,6 +105,7 @@ Tunnel=
 Gateway=
 IPv4LL=
 IPVLAN=
+IPVTAP=
 EmitLLDP=
 IPv6MTUBytes=
 IPv4ProxyARP=
@@ -188,6 +198,7 @@ RouteTable=
 UseDNS=
 UseAutonomousPrefix=
 UseOnLinkPrefix=
+BlackList=
 [DHCPServer]
 EmitNTP=
 PoolSize=
diff --git a/test/fuzz/fuzz-varlink/array b/test/fuzz/fuzz-varlink/array
new file mode 100644 (file)
index 0000000..f3ee40b
Binary files /dev/null and b/test/fuzz/fuzz-varlink/array differ
diff --git a/test/fuzz/fuzz-varlink/do-something b/test/fuzz/fuzz-varlink/do-something
new file mode 100644 (file)
index 0000000..3b124cb
Binary files /dev/null and b/test/fuzz/fuzz-varlink/do-something differ
diff --git a/test/fuzz/fuzz-varlink/huge-method b/test/fuzz/fuzz-varlink/huge-method
new file mode 100644 (file)
index 0000000..a480e41
--- /dev/null
@@ -0,0 +1 @@
+{"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "}\0
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/method-call b/test/fuzz/fuzz-varlink/method-call
new file mode 100644 (file)
index 0000000..8654a7c
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-call differ
diff --git a/test/fuzz/fuzz-varlink/method-error b/test/fuzz/fuzz-varlink/method-error
new file mode 100644 (file)
index 0000000..9ce68d8
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-error differ
diff --git a/test/fuzz/fuzz-varlink/method-reply b/test/fuzz/fuzz-varlink/method-reply
new file mode 100644 (file)
index 0000000..cd4bd94
Binary files /dev/null and b/test/fuzz/fuzz-varlink/method-reply differ
diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14688 b/test/fuzz/fuzz-varlink/oss-fuzz-14688
new file mode 100644 (file)
index 0000000..9d615db
--- /dev/null
@@ -0,0 +1 @@
+                                                                                                      {"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       "}\0                                                                       
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/oss-fuzz-14708 b/test/fuzz/fuzz-varlink/oss-fuzz-14708
new file mode 100644 (file)
index 0000000..d4391cd
--- /dev/null
@@ -0,0 +1 @@
+                                                                                                                                                 {"method":"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           "}\0                                                       {   "method": "         "}\0                                                                 {   "method": "         "}\0                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            vvvvvvvv\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\ No newline at end of file
diff --git a/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf b/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf
new file mode 100644 (file)
index 0000000..b0d8618
Binary files /dev/null and b/test/fuzz/fuzz-varlink/timeout-d8a88bf4adea54537d21e3afb396e1a55c5b58bf differ
index 50c6e9690251a6c2b5c2a347ec4e0ce5a99c7799..0394076f0aafc4350d950efa15687324e36e610d 100644 (file)
@@ -14,7 +14,7 @@ NSPAWN_TIMEOUT="${NSPAWN_TIMEOUT:-infinity}"
 TIMED_OUT=  # will be 1 after run_* if *_TIMEOUT is set and test timed out
 [[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE="${FSTYPE:-btrfs}" || FSTYPE="${FSTYPE:-ext4}"
 UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}"
-EFI_MOUNT="$(bootctl -p 2>/dev/null || echo /boot)"
+EFI_MOUNT="$(bootctl -x 2>/dev/null || echo /boot)"
 QEMU_MEM="${QEMU_MEM:-512M}"
 
 if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then
@@ -50,7 +50,7 @@ IS_BUILT_WITH_ASAN=$(is_built_with_asan && echo yes || echo no)
 
 if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then
     STRIP_BINARIES=no
-    SKIP_INITRD=yes
+    SKIP_INITRD="${SKIP_INITRD:-yes}"
     PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan
     QEMU_MEM="1536M"
     QEMU_SMP=4
@@ -378,7 +378,12 @@ find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\
 # But, apparently, sometimes it doesn't work: https://github.com/google/sanitizers/issues/886.
 JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d
 mkdir -p "\$JOURNALD_CONF_DIR"
-printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
+printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:log_path=/systemd-journald.ubsan.log\n" >"\$JOURNALD_CONF_DIR/env.conf"
+
+# Sometimes UBSan sends its reports to stderr regardless of what is specified in log_path
+# Let's try to catch them by redirecting stderr (and stdout just in case) to a file
+# See https://github.com/systemd/systemd/pull/12524#issuecomment-491108821
+printf "[Service]\nStandardOutput=file:/systemd-journald.out\n" >"\$JOURNALD_CONF_DIR/out.conf"
 
 # 90s isn't enough for some services to finish when literally everything is run
 # under ASan+UBSan in containers, which, in turn, are run in VMs.
@@ -386,6 +391,22 @@ printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/sys
 mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d
 printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf
 
+# Let's override another hard-coded timeout that kicks in too early
+mkdir -p /etc/systemd/system/systemd-journal-flush.service.d
+printf "[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-journal-flush.service.d/timeout.conf
+
+# The 'mount' utility doesn't behave well under libasan, causing unexpected
+# fails during boot and subsequent test results check:
+# bash-5.0# mount -o remount,rw -v /
+# mount: /dev/sda1 mounted on /.
+# bash-5.0# echo \$?
+# 1
+# Let's workaround this by clearing the previously set LD_PRELOAD env variable,
+# so the libasan library is not loaded for this particular service
+REMOUNTFS_CONF_DIR=/etc/systemd/system/systemd-remount-fs.service.d
+mkdir -p "\$REMOUNTFS_CONF_DIR"
+printf "[Service]\nUnsetEnvironment=LD_PRELOAD\n" >"\$REMOUNTFS_CONF_DIR/env.conf"
+
 export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS
 exec  $ROOTLIBDIR/systemd "\$@"
 EOF
@@ -496,9 +517,10 @@ check_asan_reports() {
             ret=$(($ret+1))
         fi
 
-        journald_report=$(find "$root" -name "systemd-journald.asan.log*" -exec cat {} \;)
+        journald_report=$(find "$root" -name "systemd-journald.*san.log*" -exec cat {} \;)
         if [[ ! -z "$journald_report" ]]; then
-            printf "%s" "$journald_report"
+            printf "%s\n" "$journald_report"
+            cat "$root/systemd-journald.out" || true
             ret=$(($ret+1))
         fi
 
diff --git a/test/test-network/conf/25-ipvtap.netdev b/test/test-network/conf/25-ipvtap.netdev
new file mode 100644 (file)
index 0000000..cd6aec2
--- /dev/null
@@ -0,0 +1,6 @@
+[NetDev]
+Name=ipvtap99
+Kind=ipvtap
+
+[IPVLAN]
+Mode=L2
index 50b2ce0c3bc1c55ea2357c97b34f4b4d1fa7c25b..9e12480a658dd48761e0e6a9852472382077b805 100644 (file)
@@ -5,6 +5,8 @@ Name=dummy98
 IPv6AcceptRA=no
 Address=2001:1234:5:8f63::1/128
 Address=149.10.124.58/28
+DefaultRouteOnDevice=yes
+IPv4LLRoute=yes
 
 [Route]
 Destination=2001:1234:5:8fff:ff:ff:ff:ff/128
diff --git a/test/test-network/conf/25-tunnel-local-any.network b/test/test-network/conf/25-tunnel-local-any.network
new file mode 100644 (file)
index 0000000..8ce05ad
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun98 *tap98 ip6tnl98 erspan98
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::17/64
+Address=10.3.2.4/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-tunnel-remote-any.network b/test/test-network/conf/25-tunnel-remote-any.network
new file mode 100644 (file)
index 0000000..becdcaa
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun97 ip6tnl97
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::18/64
+Address=10.3.2.5/16
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-tunnel.network b/test/test-network/conf/25-tunnel.network
new file mode 100644 (file)
index 0000000..32c1986
--- /dev/null
@@ -0,0 +1,8 @@
+[Match]
+Name=*tun99 *tap99 ip6tnl99 erspan99
+
+[Network]
+IPv6AcceptRA=no
+Address=2001:db8:0:f102::16/64
+Address=10.3.2.3/16
+LinkLocalAddressing=yes
index 1f70c3b86d60ed3dcb9417fd4b1c6a100ffc7c31..8b2e934f7fbf94fe5df1d7f6f21bc9651b42fabc 100644 (file)
@@ -3,3 +3,4 @@ Name=veth99
 
 [Network]
 DHCP=ipv6
+IPv6Token=::1a:2b:3c:4d
diff --git a/test/test-network/conf/ipvtap.network b/test/test-network/conf/ipvtap.network
new file mode 100644 (file)
index 0000000..c81ba52
--- /dev/null
@@ -0,0 +1,5 @@
+[Match]
+Name=test1
+
+[Network]
+IPVTAP=ipvtap99
index 4301f8c5dc73b36fe625596249309fd1bed45c1b..224726f9118271eaff5b1be6280f7de2fb4fad7f 100755 (executable)
@@ -70,6 +70,33 @@ def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable():
 
     return f
 
+def expectedFailureIf_ip6gre_do_not_support_ipv6ll():
+    def f(func):
+        success = False
+        rc = subprocess.call(['ip', 'link', 'add', 'name', 'test1', 'type', 'dummy'])
+        if rc == 0:
+            time.sleep(1)
+            rc = subprocess.call(['ip', 'tunnel', 'add', 'tun99', 'local', '2a00:ffde:4567:edde::4986', 'remote', '2001:473:fece:cafe::5178', 'mode', 'ip6gre', 'dev', 'test1'])
+            if rc == 0:
+                time.sleep(1)
+                # Not sure why, but '0' or '2' do not work.
+                subprocess.call(['sysctl', '-w', 'net.ipv6.conf.tun99.addr_gen_mode=3'])
+
+                output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'tun99', 'scope', 'link'], universal_newlines=True).rstrip()
+                print(output)
+                success = 'inet6' in output
+
+                subprocess.run(['ip', 'tunnel', 'del', 'tun99'])
+
+            subprocess.run(['ip', 'link', 'del', 'test1'])
+
+        if success:
+            return func
+        else:
+            return unittest.expectedFailure(func)
+
+    return f
+
 def setUpModule():
     os.makedirs(network_unit_file_path, exist_ok=True)
     os.makedirs(networkd_ci_path, exist_ok=True)
@@ -110,7 +137,7 @@ class Utilities():
         time.sleep(1)
 
     def l2tp_tunnel_remove(self, tunnel_ids):
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel'], universal_newlines=True).rstrip()
         for tid in tunnel_ids:
             words='Tunnel ' + tid + ', encap'
             if words in output:
@@ -191,6 +218,19 @@ class Utilities():
             args += ['--any']
         subprocess.check_call(args)
 
+    def get_operstate(self, link, show_status=True, setup_state='configured'):
+        output = subprocess.check_output(['networkctl', 'status', link], universal_newlines=True).rstrip()
+        if show_status:
+            print(output)
+        for line in output.splitlines():
+            if 'State:' in line and (not setup_state or setup_state in line):
+                return line.split()[1]
+        return None
+
+    def check_operstate(self, link, expected, show_status=True, setup_state='configured'):
+        self.assertRegex(self.get_operstate(link, show_status, setup_state), expected)
+
+
 class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
     links =[
@@ -222,6 +262,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'ipiptun98',
         'ipiptun99',
         'ipvlan99',
+        'ipvtap99',
         'isataptun99',
         'macvlan99',
         'macvtap99',
@@ -289,6 +330,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-ipip-tunnel-remote-any.netdev',
         '25-ipip-tunnel.netdev',
         '25-ipvlan.netdev',
+        '25-ipvtap.netdev',
         '25-isatap-tunnel.netdev',
         '25-macsec.key',
         '25-macsec.netdev',
@@ -298,6 +340,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         '25-sit-tunnel.netdev',
         '25-tap.netdev',
         '25-tun.netdev',
+        '25-tunnel-local-any.network',
+        '25-tunnel-remote-any.network',
+        '25-tunnel.network',
         '25-vcan.netdev',
         '25-veth.netdev',
         '25-vrf.netdev',
@@ -324,6 +369,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         'ip6tnl.network',
         'ipip.network',
         'ipvlan.network',
+        'ipvtap.network',
         'isatap.network',
         'macsec.network',
         'macvlan.network',
@@ -349,29 +395,29 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         # This also tests NetDev.Name= conflict and basic networkctl functionalities
 
-        output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'link', 'show', 'dropin-test'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '00:50:56:c0:00:28')
 
-        output = subprocess.check_output(['networkctl', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list'], universal_newlines=True).rstrip()
         self.assertRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'list', 'dropin-test']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list', 'dropin-test'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'list', 'dropin-*']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'list', 'dropin-*'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1 lo ')
         self.assertRegex(output, 'dropin-test')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dropin-*']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dropin-*'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, '1: lo ')
         self.assertRegex(output, 'dropin-test')
 
-        ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-        print(ret.stdout.rstrip().decode('utf-8'))
-        if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip().decode('utf-8')) != None:
+        ret = subprocess.run(['ethtool', '--driver', 'dropin-test'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
+        print(ret.stdout.rstrip())
+        if ret.returncode == 0 and re.search('driver: dummy', ret.stdout.rstrip()) != None:
             self.assertRegex(output, 'Driver: dummy')
         else:
             print('ethtool does not support driver field at least for dummy interfaces, skipping test for Driver field of networkctl.')
@@ -384,13 +430,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('bridge99'))
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: (?:off|no-carrier) \(configuring\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded \(configured\)')
+        self.check_operstate('bridge99', '(?:off|no-carrier)', setup_state='configuring')
+        self.check_operstate('test1', 'degraded')
 
     def test_bridge(self):
         self.copy_unit_to_networkd_unit_path('25-bridge.netdev')
@@ -442,11 +483,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('vlan99'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
-        self.assertRegex(output, ' mtu 2004 ')
+        self.assertRegex(output, ' mtu 2000 ')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, ' mtu 2000 ')
         self.assertRegex(output, 'REORDER_HDR')
@@ -455,12 +496,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'MVRP')
         self.assertRegex(output, ' id 99 ')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.24.5/24 brd 192.168.24.255 scope global test1')
         self.assertRegex(output, 'inet 192.168.25.5/24 brd 192.168.25.255 scope global test1')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'vlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.23.5/24 brd 192.168.23.255 scope global vlan99')
 
@@ -477,11 +518,11 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('macvlan99'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, ' mtu 2000 ')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macvlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, ' mtu 2000 ')
 
@@ -492,6 +533,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('ipvlan99'))
 
+    @expectedFailureIfModuleIsNotAvailable('ipvtap')
+    def test_ipvtap(self):
+        self.copy_unit_to_networkd_unit_path('25-ipvtap.netdev', '11-dummy.netdev', 'ipvtap.network')
+        self.start_networkd()
+
+        self.assertTrue(self.link_exits('ipvtap99'))
+
     def test_veth(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev')
         self.start_networkd()
@@ -544,24 +592,24 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         if shutil.which('wg'):
             subprocess.call('wg')
 
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port'], universal_newlines=True).rstrip()
             self.assertRegex(output, '51820')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark'], universal_newlines=True).rstrip()
             self.assertRegex(output, '0x4d2')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48')
             self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=\tfdbc:bae2:7871:e1fe:793:8636::/96 fdbc:bae2:7871:500:e1fe:793:8636:dad1/128')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t20')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=\t192.168.27.3:51820')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'private-key'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'EEGlnEPYJV//kbvvIqxKkQwOiS\+UENyPncC4bF46ong=')
-            output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg99', 'preshared-keys'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'RDf\+LSpeEre7YEIKaxg\+wbpsNV7du\+ktR99uBEtIiCA=  IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M=')
             self.assertRegex(output, 'lsDtM3AbjxNlauRKzHEPfgS1Zp7cp/VX5Use/P4PQSc=     cPLOy1YUrEI0EMMIycPJmOo0aTu3RZnw8bL5meVD6m0=')
 
-            output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['wg', 'show', 'wg98', 'private-key'], universal_newlines=True).rstrip()
             self.assertRegex(output, 'CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr\+WHtZLZ90FU=')
 
     def test_geneve(self):
@@ -570,7 +618,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('geneve99'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'geneve99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.22.1')
         self.assertRegex(output, '6082')
@@ -578,50 +626,46 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'udp6zerocsumrx')
 
     def test_ipip_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ipip-tunnel.netdev', 'ipip.network',
-                                             '25-ipip-tunnel-local-any.netdev', '25-ipip-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ipiptun99'))
-        self.assertTrue(self.link_exits('ipiptun98'))
-        self.assertTrue(self.link_exits('ipiptun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ipip.network',
+                                             '25-ipip-tunnel.netdev', '25-tunnel.network',
+                                             '25-ipip-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ipip-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ipiptun99:routable', 'ipiptun98:routable', 'ipiptun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local 192.168.223.238 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote 192.169.224.239 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ipip (?:ipip |)remote any local 192.168.223.238 dev dummy98')
 
     def test_gre_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gre-tunnel.netdev', 'gretun.network',
-                                             '25-gre-tunnel-local-any.netdev', '25-gre-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('gretun99'))
-        self.assertTrue(self.link_exits('gretun98'))
-        self.assertTrue(self.link_exits('gretun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretun.network',
+                                             '25-gre-tunnel.netdev', '25-tunnel.network',
+                                             '25-gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['gretun99:routable', 'gretun98:routable', 'gretun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote 10.65.223.239 local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 1.2.3.103')
         self.assertRegex(output, 'okey 1.2.4.103')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote 10.65.223.239 local any dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.104')
         self.assertRegex(output, 'okey 0.0.0.104')
         self.assertNotRegex(output, 'iseq')
         self.assertNotRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gre remote any local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.105')
@@ -629,9 +673,12 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertNotRegex(output, 'iseq')
         self.assertNotRegex(output, 'oseq')
 
+    @expectedFailureIf_ip6gre_do_not_support_ipv6ll()
     def test_ip6gre_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gre-tunnel.netdev', 'ip6gretun.network',
-                                             '25-ip6gre-tunnel-local-any.netdev', '25-ip6gre-tunnel-remote-any.netdev')
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretun.network',
+                                             '25-ip6gre-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6gre-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ip6gre-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
         self.start_networkd()
 
         self.assertTrue(self.link_exits('dummy98'))
@@ -639,33 +686,34 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('ip6gretun98'))
         self.assertTrue(self.link_exits('ip6gretun97'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote 2001:473:fece:cafe::5179 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gre remote any local 2a00:ffde:4567:edde::4987 dev dummy98')
 
-    def test_gretap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-gretap-tunnel.netdev', 'gretap.network',
-                                             '25-gretap-tunnel-local-any.netdev')
-        self.start_networkd()
+        # Old kernels may not support IPv6LL address on ip6gre tunnel, and the following test may fails.
+        self.wait_online(['ip6gretun99:routable', 'ip6gretun98:routable', 'ip6gretun97:routable', 'dummy98:degraded'])
 
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('gretap99'))
-        self.assertTrue(self.link_exits('gretap98'))
+    def test_gretap_tunnel(self):
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'gretap.network',
+                                             '25-gretap-tunnel.netdev', '25-tunnel.network',
+                                             '25-gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['gretap99:routable', 'gretap98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gretap remote 10.65.223.239 local 10.65.223.238 dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.106')
         self.assertRegex(output, 'okey 0.0.0.106')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
         self.assertRegex(output, 'ikey 0.0.0.107')
@@ -674,142 +722,130 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'oseq')
 
     def test_ip6gretap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6gretap-tunnel.netdev', 'ip6gretap.network',
-                                             '25-ip6gretap-tunnel-local-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ip6gretap99'))
-        self.assertTrue(self.link_exits('ip6gretap98'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6gretap.network',
+                                             '25-ip6gretap-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6gretap-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ip6gretap99:routable', 'ip6gretap98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6gretap98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6gretap remote 2001:473:fece:cafe::5179 local any dev dummy98')
 
     def test_vti_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti-tunnel.netdev', 'vti.network',
-                                             '25-vti-tunnel-local-any.netdev', '25-vti-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('vtitun99'))
-        self.assertTrue(self.link_exits('vtitun98'))
-        self.assertTrue(self.link_exits('vtitun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti.network',
+                                             '25-vti-tunnel.netdev', '25-tunnel.network',
+                                             '25-vti-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-vti-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['vtitun99:routable', 'vtitun98:routable', 'vtitun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote 10.65.223.239 local 10.65.223.238 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote 10.65.223.239 local any dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vtitun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti remote any local 10.65.223.238 dev dummy98')
 
     def test_vti6_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-vti6-tunnel.netdev', 'vti6.network',
-                                             '25-vti6-tunnel-local-any.netdev', '25-vti6-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('vti6tun99'))
-        self.assertTrue(self.link_exits('vti6tun98'))
-        self.assertTrue(self.link_exits('vti6tun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'vti6.network',
+                                             '25-vti6-tunnel.netdev', '25-tunnel.network',
+                                             '25-vti6-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-vti6-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['vti6tun99:routable', 'vti6tun98:routable', 'vti6tun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vti6tun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vti6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
 
     def test_ip6tnl_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl-tunnel.netdev', 'ip6tnl.network',
-                                             '25-ip6tnl-tunnel-local-any.netdev', '25-ip6tnl-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('ip6tnl99'))
-        self.assertTrue(self.link_exits('ip6tnl98'))
-        self.assertTrue(self.link_exits('ip6tnl97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'ip6tnl.network',
+                                             '25-ip6tnl-tunnel.netdev', '25-tunnel.network',
+                                             '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local 2a00:ffde:4567:edde::4987 dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote 2001:473:fece:cafe::5179 local (?:any|::) dev dummy98')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ip6tnl97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'ip6tnl ip6ip6 remote (?:any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')
 
     def test_sit_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit-tunnel.netdev', 'sit.network',
-                                             '25-sit-tunnel-local-any.netdev',
-                                             '25-sit-tunnel-remote-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('sittun99'))
-        self.assertTrue(self.link_exits('sittun98'))
-        self.assertTrue(self.link_exits('sittun97'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'sit.network',
+                                             '25-sit-tunnel.netdev', '25-tunnel.network',
+                                             '25-sit-tunnel-local-any.netdev', '25-tunnel-local-any.network',
+                                             '25-sit-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')
+        self.start_networkd(0)
+        self.wait_online(['sittun99:routable', 'sittun98:routable', 'sittun97:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local 10.65.223.238 dev dummy98")
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote 10.65.223.239 local any dev dummy98")
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun97'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "sit (?:ip6ip |)remote any local 10.65.223.238 dev dummy98")
 
     def test_isatap_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-isatap-tunnel.netdev', 'isatap.network')
-        self.start_networkd()
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'isatap.network',
+                                             '25-isatap-tunnel.netdev', '25-tunnel.network')
+        self.start_networkd(0)
+        self.wait_online(['isataptun99:routable', 'dummy98:degraded'])
 
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('isataptun99'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'isataptun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "isatap ")
 
     def test_6rd_tunnel(self):
-        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-6rd-tunnel.netdev', '6rd.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('sittun99'))
+        self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '6rd.network',
+                                             '25-6rd-tunnel.netdev', '25-tunnel.network')
+        self.start_networkd(0)
+        self.wait_online(['sittun99:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '6rd-prefix 2602::/24')
 
     @expectedFailureIfERSPANModuleIsNotAvailable()
     def test_erspan_tunnel(self):
         self.copy_unit_to_networkd_unit_path('12-dummy.netdev', 'erspan.network',
-                                             '25-erspan-tunnel.netdev', '25-erspan-tunnel-local-any.netdev')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('dummy98'))
-        self.assertTrue(self.link_exits('erspan99'))
-        self.assertTrue(self.link_exits('erspan98'))
+                                             '25-erspan-tunnel.netdev', '25-tunnel.network',
+                                             '25-erspan-tunnel-local-any.netdev', '25-tunnel-local-any.network')
+        self.start_networkd(0)
+        self.wait_online(['erspan99:routable', 'erspan98:routable', 'dummy98:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'erspan remote 172.16.1.100 local 172.16.1.200')
         self.assertRegex(output, 'ikey 0.0.0.101')
         self.assertRegex(output, 'okey 0.0.0.101')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'erspan98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'erspan remote 172.16.1.100 local any')
         self.assertRegex(output, '102')
@@ -840,21 +876,21 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('gretun96'))
         self.assertTrue(self.link_exits('gretap96'))
 
-        output = subprocess.check_output(['ip', 'fou', 'show']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'fou', 'show'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'port 55555 ipproto 4')
         self.assertRegex(output, 'port 55556 ipproto 47')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'ipiptun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'sittun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55555')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretun96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport 1001 encap-dport 55556')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'gretap96'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
 
@@ -868,7 +904,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.wait_online(['test1:degraded', 'vxlan99:degraded'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'vxlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '999')
         self.assertRegex(output, '5555')
@@ -881,7 +917,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'remcsumrx')
         self.assertRegex(output, 'gbp')
 
-        output = subprocess.check_output(['bridge', 'fdb', 'show', 'dev', 'vxlan99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['bridge', 'fdb', 'show', 'dev', 'vxlan99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '00:11:22:33:44:55 dst 10.0.0.5 self permanent')
         self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
@@ -894,13 +930,13 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:degraded', 'macsec99:routable'])
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macsec99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'macsec99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'macsec99@dummy98')
         self.assertRegex(output, 'macsec sci [0-9a-f]*000b')
         self.assertRegex(output, 'encrypt on')
 
-        output = subprocess.check_output(['ip', 'macsec', 'show', 'macsec99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'macsec', 'show', 'macsec99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'encrypt on')
         self.assertRegex(output, 'TXSC: [0-9a-f]*000b on SA 1')
@@ -951,7 +987,7 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('l2tp-ses1'))
         self.assertTrue(self.link_exits('l2tp-ses2'))
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Tunnel 10, encap UDP")
         self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
@@ -959,13 +995,13 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
         self.assertRegex(output, "UDP source / dest ports: 3000/4000")
         self.assertRegex(output, "UDP checksum: enabled")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '15'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 15 in tunnel 10")
         self.assertRegex(output, "Peer session 16, tunnel 11")
         self.assertRegex(output, "interface name: l2tp-ses1")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '17'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 17 in tunnel 10")
         self.assertRegex(output, "Peer session 18, tunnel 11")
@@ -980,19 +1016,19 @@ class NetworkdL2TPTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('l2tp-ses3'))
         self.assertTrue(self.link_exits('l2tp-ses4'))
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'tunnel', 'tunnel_id', '10'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Tunnel 10, encap IP")
         self.assertRegex(output, "From 192.168.30.100 to 192.168.30.101")
         self.assertRegex(output, "Peer tunnel 12")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '25'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 25 in tunnel 10")
         self.assertRegex(output, "Peer session 26, tunnel 12")
         self.assertRegex(output, "interface name: l2tp-ses3")
 
-        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'l2tp', 'show', 'session', 'tid', '10', 'session_id', '27'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, "Session 27 in tunnel 10")
         self.assertRegex(output, "Peer session 28, tunnel 12")
@@ -1042,7 +1078,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:routable'])
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.1.2.3/16 brd 10.1.255.255 scope global dummy98')
         self.assertRegex(output, 'inet 10.1.2.4/16 brd 10.1.255.255 scope global secondary dummy98')
@@ -1052,19 +1088,19 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertNotRegex(output, '10.10.0.1/16')
         self.assertNotRegex(output, '10.10.0.2/16')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '32'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 10.3.2.3/16 brd 10.3.255.255 scope global 32')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '33'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 10.4.2.3 peer 10.4.2.4/16 scope global 33')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '34'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 192.168.[0-9]*.1/24 brd 192.168.[0-9]*.255 scope global 34')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'dummy98', 'label', '35'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 172.[0-9]*.0.1/16 brd 172.[0-9]*.255.255 scope global 35')
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet6 2001:db8:0:f101::15/64 scope global')
         self.assertRegex(output, 'inet6 2001:db8:0:f101::16/64 scope global')
@@ -1079,11 +1115,9 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configuring\)')
+        self.check_operstate('dummy98', 'routable', setup_state='configuring')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope link deprecated dummy98')
         self.assertRegex(output, 'inet6 2001:db8:0:f101::1/64 scope global')
@@ -1094,7 +1128,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.15')
         self.assertRegex(output, '192.168.0.1')
@@ -1109,7 +1143,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'from 192.168.100.18')
@@ -1134,11 +1168,11 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
             self.assertTrue(self.link_exits('test1'))
             self.assertTrue(self.link_exits('dummy98'))
 
-            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '7'], universal_newlines=True).rstrip()
             print(output)
             self.assertRegex(output, '111:     from 192.168.100.18 tos (?:0x08|throughput) iif test1 oif test1 lookup 7')
 
-            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8']).rstrip().decode('utf-8')
+            output = subprocess.check_output(['ip', 'rule', 'list', 'table', '8'], universal_newlines=True).rstrip()
             print(output)
             self.assertRegex(output, '112:     from 192.168.101.18 tos (?:0x08|throughput) iif dummy98 oif dummy98 lookup 8')
 
@@ -1155,7 +1189,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'from 192.168.100.18')
@@ -1176,7 +1210,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['ip', 'rule']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '111')
         self.assertRegex(output, 'not.*?from.*?192.168.100.18')
@@ -1191,34 +1225,36 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.wait_online(['dummy98:routable'])
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2001:1234:5:8fff:ff:ff:ff:ff proto static')
         self.assertRegex(output, '2001:1234:5:8f63::1 proto kernel')
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'default via 2001:1234:5:8fff:ff:ff:ff:ff proto static metric 1024 pref medium')
 
-        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '149.10.124.48/28 proto kernel scope link src 149.10.124.58')
         self.assertRegex(output, '149.10.124.64 proto static scope link')
+        self.assertRegex(output, '169.254.0.0/16 proto static scope link metric 2048')
         self.assertRegex(output, '192.168.1.1 proto static initcwnd 20')
         self.assertRegex(output, '192.168.1.2 proto static initrwnd 30')
 
-        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'route', 'show', 'dev', 'dummy98', 'default'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'default via 149.10.125.65 proto static onlink')
         self.assertRegex(output, 'default via 149.10.124.64 proto static')
+        self.assertRegex(output, 'default proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'blackhole'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'blackhole 202.54.1.2 proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'unreachable'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'unreachable 202.54.1.3 proto static')
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'type', 'prohibit'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'prohibit 202.54.1.4 proto static')
 
@@ -1236,7 +1272,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('bond199'))
 
-        output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'abcd::/16')
         self.assertRegex(output, 'src')
@@ -1248,7 +1284,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '00:01:02:aa:bb:cc')
 
@@ -1258,7 +1294,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'unmanaged')
 
@@ -1268,7 +1304,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', 'addrlabel', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addrlabel', 'list'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2004:da8:1::/64')
 
@@ -1278,7 +1314,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'neigh', 'list'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT')
         self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT')
@@ -1292,22 +1328,17 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet .* scope link')
         self.assertRegex(output, 'inet6 .* scope link')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'inet6* .* scope link')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: carrier \(configured\)')
+        self.check_operstate('test1', 'degraded')
+        self.check_operstate('dummy98', 'carrier')
 
         '''
         Documentation/networking/ip-sysctl.txt
@@ -1369,14 +1400,13 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '')
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
 
@@ -1389,14 +1419,13 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 10.2.3.4/16 brd 10.2.255.255 scope global dummy98')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet6 .* scope link')
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'routable')
 
     def test_bind_carrier(self):
         self.copy_unit_to_networkd_unit_path('25-bind-carrier.network', '11-dummy.netdev')
@@ -1407,51 +1436,46 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities):
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy99', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy99', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy99']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'DOWN')
         self.assertNotRegex(output, '192.168.10')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: off \(configured\)')
+        self.check_operstate('test1', 'off')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'add', 'dummy98', 'type', 'dummy']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
-        output = subprocess.check_output(['ip', 'address', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'UP,LOWER_UP')
         self.assertRegex(output, 'inet 192.168.10.30/24 brd 192.168.10.255 scope global test1')
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'routable')
 
 class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
     links = [
@@ -1486,7 +1510,7 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('bond199'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'active_slave dummy98')
 
@@ -1497,7 +1521,7 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('bond199'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond199'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'primary test1')
 
@@ -1510,75 +1534,55 @@ class NetworkdNetWorkBondTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('dummy98'))
         self.assertTrue(self.link_exits('test1'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'SLAVE,UP,LOWER_UP')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'bond99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'MASTER,UP,LOWER_UP')
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
         time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: degraded-carrier \(configured\)')
+        self.check_operstate('dummy98', 'off')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'degraded-carrier')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'up']), 0)
         time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('bond99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'dummy98', 'down']), 0)
         self.assertEqual(subprocess.call(['ip', 'link', 'set', 'test1', 'down']), 0)
-        time.sleep(5)
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
+        time.sleep(2)
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: off \(configured\)')
+        self.check_operstate('dummy98', 'off')
+        self.check_operstate('test1', 'off')
 
-        output = subprocess.check_output(['networkctl', 'status', 'bond99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: no-carrier \(configured\)')
+        bond_has_no_carrier=False
+        for trial in range(30):
+            if trial > 0:
+                time.sleep(1)
+            output = subprocess.check_output(['ip', 'address', 'show', 'bond99'], universal_newlines=True).rstrip()
+            print(output)
+            if self.get_operstate('bond99') == 'no-carrier':
+                break
+        else:
+            # Huh? Kernel does not recognize that all slave interfaces are down?
+            # Let's confirm that networkd's operstate is consistent with ip's result.
+            self.assertNotRegex(output, 'NO-CARRIER')
 
 class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
     links = [
@@ -1612,21 +1616,21 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         self.assertTrue(self.link_exits('test1'))
         self.assertTrue(self.link_exits('bridge99'))
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'test1'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'master')
         self.assertRegex(output, 'bridge')
 
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'master')
         self.assertRegex(output, 'bridge')
 
-        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.15/24')
 
-        output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['bridge', '-d', 'link', 'show', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'hairpin_mode'), '1')
         self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'path_cost'), '400')
@@ -1641,38 +1645,30 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         if (os.path.exists('/sys/devices/virtual/net/bridge00/lower_dummy98/brport/multicast_to_unicast')):
             self.assertEqual(self.read_bridge_port_attr('bridge99', 'dummy98', 'multicast_to_unicast'), '1')
 
-        output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('test1', 'enslaved')
+        self.check_operstate('dummy98', 'enslaved')
+        self.check_operstate('bridge99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'address', 'add', '192.168.0.16/24', 'dev', 'bridge99']), 0)
         time.sleep(1)
 
-        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'addr', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.0.16/24')
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('bridge99', 'routable')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'test1']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: degraded-carrier \(configured\)')
+        self.check_operstate('bridge99', 'degraded-carrier')
 
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: no-carrier \(configured\)')
+        self.check_operstate('bridge99', 'no-carrier')
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'NO-CARRIER')
         self.assertNotRegex(output, '192.168.0.15/24')
@@ -1698,7 +1694,7 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
         self.assertEqual(subprocess.call(['ip', 'link', 'del', 'dummy98']), 0)
         time.sleep(3)
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'NO-CARRIER')
         self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
@@ -1733,17 +1729,14 @@ class NetworkdNetWorkBridgeTests(unittest.TestCase, Utilities):
 
         time.sleep(3)
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'bridge99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'inet 192.168.0.15/24 brd 192.168.0.255 scope global bridge99')
 
-        output = subprocess.check_output(['networkctl', 'status', 'bridge99']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: routable \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
-        self.assertRegex(output, 'State: enslaved \(configured\)')
+        self.check_operstate('bridge99', 'routable')
+        self.check_operstate('dummy98', 'enslaved')
 
-        output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'rule', 'list', 'table', '100'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '0:   from all to 8.8.8.8 lookup 100')
 
@@ -1770,7 +1763,7 @@ class NetworkdNetWorkLLDPTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        output = subprocess.check_output(['networkctl', 'lldp']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'lldp'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'veth-peer')
         self.assertRegex(output, 'veth99')
@@ -1796,7 +1789,7 @@ class NetworkdNetworkRATests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2002:da8:1:0')
 
@@ -1827,7 +1820,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
         self.assertRegex(output, 'Gateway: 192.168.5.1')
@@ -1840,7 +1833,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('dummy98'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'dummy98'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'Address: 192.168.42.100')
         self.assertRegex(output, 'DNS: 192.168.42.1')
@@ -1852,7 +1845,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'Gateway: 192.168.5.*')
         self.assertRegex(output, '192.168.5.*')
@@ -1900,17 +1893,22 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
     def test_dhcp_client_ipv6_only(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network')
-        self.start_networkd()
-
-        self.assertTrue(self.link_exits('veth99'))
 
+        self.start_networkd(0)
+        self.wait_online(['veth-peer:carrier'])
         self.start_dnsmasq()
+        self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertNotRegex(output, '192.168.5')
 
+        # Confirm that ipv6 token is not set in the kernel
+        output = subprocess.check_output(['ip', 'token', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
+        print(output)
+        self.assertRegex(output, 'token :: dev veth99')
+
     def test_dhcp_client_ipv4_only(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network')
         self.start_networkd()
@@ -1919,7 +1917,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, '2600::')
         self.assertRegex(output, '192.168.5')
@@ -1933,7 +1931,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertRegex(output, '192.168.5')
@@ -1947,7 +1945,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.start_dnsmasq()
 
         print('## ip address show dev veth99')
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertRegex(output, '192.168.5')
@@ -1955,12 +1953,12 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         # issue #8726
         print('## ip route show table main dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertNotRegex(output, 'proto dhcp')
 
         print('## ip route show table 211 dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', '211', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 proto dhcp')
         self.assertRegex(output, '192.168.5.0/24 via 192.168.5.5 proto dhcp')
@@ -1980,7 +1978,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertTrue(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
@@ -1993,7 +1991,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '12:34:56:78:9a:bc')
         self.assertFalse(self.search_words_in_dnsmasq_log('14:rapid-commit', True))
@@ -2018,7 +2016,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq('--dhcp-alternate-port=67,5555')
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.* dynamic')
 
@@ -2030,7 +2028,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', '12']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', '12'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'veth99 proto dhcp')
         self.assertRegex(output, '192.168.5.1')
@@ -2043,7 +2041,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'metric 24')
 
@@ -2055,7 +2053,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
 
@@ -2065,7 +2063,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         # Sleep for 120 sec as the dnsmasq minimum lease time can only be set to 120
         time.sleep(125)
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5.*')
 
@@ -2077,7 +2075,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
         self.assertRegex(output, '2600::')
@@ -2096,12 +2094,12 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.assertTrue(self.link_exits('veth99'))
 
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
         self.assertRegex(output, 'valid_lft forever preferred_lft forever')
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '2600::')
         self.assertRegex(output, 'valid_lft forever preferred_lft forever')
@@ -2118,16 +2116,16 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.start_dnsmasq()
 
         print('## ip -d link show dev vrf99')
-        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-d', 'link', 'show', 'dev', 'vrf99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'vrf table 42')
 
         print('## ip address show vrf vrf99')
-        output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
+        output_ip_vrf = subprocess.check_output(['ip', 'address', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
         print(output_ip_vrf)
 
         print('## ip address show dev veth99')
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, output_ip_vrf)
         self.assertRegex(output, 'inet 169.254.[0-9]*.[0-9]*/16 brd 169.254.255.255 scope link veth99')
@@ -2136,7 +2134,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'inet6 .* scope link')
 
         print('## ip route show vrf vrf99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'vrf', 'vrf99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'default via 192.168.5.1 dev veth99 proto dhcp src 192.168.5.')
         self.assertRegex(output, 'default dev veth99 proto static scope link')
@@ -2146,17 +2144,12 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.assertRegex(output, '192.168.5.1 dev veth99 proto dhcp scope link src 192.168.5')
 
         print('## ip route show table main dev veth99')
-        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'show', 'table', 'main', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertEqual(output, '')
 
-        output = subprocess.check_output(['networkctl', 'status', 'vrf99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: carrier \(configured\)')
-
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
-        print(output)
-        self.assertRegex(output, 'State: routable \(configured\)')
+        self.check_operstate('vrf99', 'carrier')
+        self.check_operstate('veth99', 'routable')
 
     def test_dhcp_client_gateway_onlink_implicit(self):
         self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network',
@@ -2167,14 +2160,14 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
 
         self.start_dnsmasq()
 
-        output = subprocess.check_output(['networkctl', 'status', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['networkctl', 'status', 'veth99'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, '192.168.5')
 
-        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '10.0.0.0/8'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'onlink')
-        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'route', 'list', 'dev', 'veth99', '192.168.100.0/24'], universal_newlines=True).rstrip()
         print(output)
         self.assertRegex(output, 'onlink')
 
@@ -2186,31 +2179,31 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.start_dnsmasq(lease_time='2m')
         self.wait_online(['veth99:routable', 'veth-peer:routable'])
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet6 .* scope link')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet .* scope link')
 
         print('Wait for the dynamic address to be expired')
         time.sleep(130)
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet6 .* scope link')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet .* scope link')
 
         self.search_words_in_dnsmasq_log('DHCPOFFER', show_all=True)
@@ -2221,16 +2214,16 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities):
         self.start_networkd(0)
         self.wait_online(['veth99:degraded', 'veth-peer:routable'])
 
-        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99'], universal_newlines=True).rstrip()
         print(output)
 
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet6 2600::[0-9a-f]*/128 scope global dynamic')
-        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet6 .* scope link')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global', 'dynamic'], universal_newlines=True).rstrip()
         self.assertNotRegex(output, 'inet 192.168.5.[0-9]*/24 brd 192.168.5.255 scope global dynamic veth99')
-        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link']).rstrip().decode('utf-8')
+        output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'link'], universal_newlines=True).rstrip()
         self.assertRegex(output, 'inet .* scope link')
 
 if __name__ == '__main__':
index b94a9d0f47711d40a8a1b6c519e099afff0d5809..f14b4fc6dffc6e2291a8b5b42709304eef50055a 100644 (file)
@@ -4,7 +4,7 @@ enable_tmpfiles = conf.get('ENABLE_TMPFILES') == 1
 
 tmpfiles = [['home.conf',            ''],
             ['journal-nocow.conf',   ''],
-            ['systemd-nologin.conf', ''],
+            ['systemd-nologin.conf', 'HAVE_PAM'],
             ['systemd-nspawn.conf',  'ENABLE_MACHINED'],
             ['systemd-tmp.conf',     ''],
             ['portables.conf',       'ENABLE_PORTABLED'],
index a8605b6bc94167b6ea2df7dc265be171da1c7e53..5dc95fa8c15ad4fd61a84c5ade936010c8594482 100755 (executable)
@@ -15,4 +15,8 @@ fi
 # Apparently git describe has a bug where it always considers the work-tree
 # dirty when invoked with --git-dir (even though 'git status' is happy). Work
 # around this issue by cd-ing to the source directory.
-cd "$dir" && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback"
+cd "$dir"
+# Check that we have either .git/ (a normal clone) or a .git file (a work-tree)
+# and that we don't get confused if a tarball is extracted in a higher-level
+# git repository.
+[ -e .git ] && git describe --abbrev=7 --dirty=+ 2>/dev/null | sed 's/^v//' || echo "$fallback"
index 610bb9c2353cda83c8e0cf593a076f1dc95d7cd3..6d9010ce16070d6935d5b2fbc513a24ec8d9e101 100755 (executable)
@@ -10,7 +10,7 @@ export CXX=${CXX:-clang++}
 clang_version="$($CC --version | sed -nr 's/.*version ([^ ]+?) .*/\1/p' | sed -r 's/-$//')"
 
 SANITIZER=${SANITIZER:-address -fsanitize-address-use-after-scope}
-flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER -fsanitize-coverage=trace-pc-guard,trace-cmp"
+flags="-O1 -fno-omit-frame-pointer -gline-tables-only -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=$SANITIZER"
 
 clang_lib="/usr/lib64/clang/${clang_version}/lib/linux"
 [ -d "$clang_lib" ] || clang_lib="/usr/lib/clang/${clang_version}/lib/linux"
@@ -33,7 +33,7 @@ if [ -z "$FUZZING_ENGINE" ]; then
 fi
 
 meson $build -D$fuzzflag -Db_lundef=false
-ninja -C $build fuzzers
+ninja -v -C $build fuzzers
 
 # The seed corpus is a separate flat archive for each fuzzer,
 # with a fixed name ${fuzzer}_seed_corpus.zip.
index d3a91ea32823f3a087f5a66ac00046c44eb913bc..0080b065d89cf201f06a2546ca782d1c393f67bd 100755 (executable)
@@ -2,8 +2,22 @@
 
 set -e
 set -x
+set -u
+
+REPO_ROOT=${REPO_ROOT:-$(pwd)}
+
+sudo bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
+sudo apt-get update -y
+sudo apt-get build-dep systemd -y
+sudo apt-get install -y ninja-build python3-pip python3-setuptools
+pip3 install meson
 
 cd $REPO_ROOT
+export PATH="$HOME/.local/bin/:$PATH"
+tools/oss-fuzz.sh
+timeout --preserve-status 5 ./out/fuzz-unit-file
+git clean -dxff
+
 wget https://app.fuzzbuzz.io/releases/cli/latest/linux/fuzzbuzz
 chmod +x fuzzbuzz
 ./fuzzbuzz validate
@@ -12,5 +26,14 @@ chmod +x fuzzbuzz
 git clone https://github.com/google/oss-fuzz /tmp/oss-fuzz
 cd /tmp/oss-fuzz
 sudo ./infra/helper.py pull_images
-sudo ./infra/helper.py build_fuzzers --clean --sanitizer=memory systemd $REPO_ROOT
-sudo ./infra/helper.py check_build --sanitizer=memory systemd
+
+# docker doesn't like colons in filenames so let's create a directory
+# whose name can be consumed by the -v option.
+# https://github.com/google/oss-fuzz/issues/2428
+t=$(mktemp -d)
+sudo mount --bind "$REPO_ROOT" "$t"
+
+# helper.py is wrapped in script to trick it into thinking it's "interactive"
+# See https://github.com/systemd/systemd/pull/12542#issuecomment-491563572
+sudo script -e -c "./infra/helper.py build_fuzzers --clean --sanitizer=memory systemd $t"
+sudo script -e -c "./infra/helper.py check_build --sanitizer=memory -e ALLOWED_BROKEN_TARGETS_PERCENTAGE=0 systemd"
index 71a65e406decbaa14dde601b9adb7dceb2b92afa..8995a51f84e4ceb7d3048e971261a94d002febaf 100755 (executable)
@@ -2,21 +2,25 @@
 set -e
 set -x
 
+bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse' >>/etc/apt/sources.list"
 apt-get update
 apt-get build-dep systemd -y
 apt-get install -y util-linux libmount-dev libblkid-dev liblzma-dev libqrencode-dev libmicrohttpd-dev iptables-dev liblz4-dev libcurl4-gnutls-dev unifont itstool kbd cryptsetup-bin net-tools isc-dhcp-client iputils-ping strace qemu-system-x86 linux-image-virtual mount libgpg-error-dev libxkbcommon-dev python-lxml python3-lxml python3-pip libcap-dev
 apt-get install -y gettext python3-evdev python3-pyparsing libmount-dev python3-setuptools ninja-build
 pip3 install meson
 
-cd $REPO_ROOT
+cd ${REPO_ROOT:-$(pwd)}
 
 sed -i 's/2\.30/2.27/' meson.build
 
 meson --werror -Db_sanitize=address,undefined -Dsplit-usr=true -Dman=true build
 ninja -v -C build
-make -C test/TEST-01-BASIC clean setup run TEST_NO_QEMU=yes NSPAWN_ARGUMENTS=--keep-unit RUN_IN_UNPRIVILEGED_CONTAINER=no
+
+make -C test/TEST-01-BASIC clean setup run NSPAWN_TIMEOUT=600 TEST_NO_QEMU=yes NSPAWN_ARGUMENTS=--keep-unit RUN_IN_UNPRIVILEGED_CONTAINER=no
 
 # Now that we're more or less sure that ASan isn't going to crash systemd and cause a kernel panic
 # let's also run the test with QEMU to cover udevd, sysctl and everything else that isn't run
 # in containers.
-make -C test/TEST-01-BASIC clean setup run TEST_NO_NSPAWN=yes
+
+# This should be turned on once `journalctl --flush` isn't flaky any more
+#make -C test/TEST-01-BASIC clean setup run QEMU_TIMEOUT=900 TEST_NO_NSPAWN=yes
index bacfe51d6f3f450d9382a4428c8296ff13fd0eee..29b006cba5775ac2fb42859e4d4505d923dac776 100644 (file)
@@ -18,6 +18,7 @@ RequiresMountsFor=/var/log/journal
 
 [Service]
 ExecStart=@rootbindir@/journalctl --flush
+ExecStop=@rootbindir@/journalctl --smart-relinquish-var
 Type=oneshot
 RemainAfterExit=yes
 TimeoutSec=90s