Compare commits

..

No commits in common. "95b29f326709bae555622e9c0cdb70529ef84356" and "d3e0662c7d531748dd3626861a21c684857fc52e" have entirely different histories.

81 changed files with 825 additions and 1449 deletions

22
README
View File

@ -262,19 +262,19 @@ USERS AND GROUPS:
NSS: NSS:
systemd ships with four glibc NSS modules: systemd ships with four glibc NSS modules:
nss-myhostname resolves the local hostname to locally configured IP nss-myhostname resolves the local hostname to locally
addresses, as well as "localhost" to 127.0.0.1/::1. configured IP addresses, as well as "localhost" to
127.0.0.1/::1.
nss-resolve enables DNS resolution via the systemd-resolved DNS/LLMNR nss-resolve enables DNS resolution via the systemd-resolved
caching stub resolver "systemd-resolved". DNS/LLMNR caching stub resolver "systemd-resolved".
nss-mymachines enables resolution of all local containers registered nss-mymachines enables resolution of all local containers registered
with machined to their respective IP addresses. with machined to their respective IP addresses. It also maps UID/GIDs
ranges used by containers to useful names.
nss-systemd enables resolution of users/group registered via the nss-systemd enables resolution of all dynamically allocated service
User/Group Record Lookup API (https://systemd.io/USER_GROUP_API/), users. (See the DynamicUser= setting in unit files.)
including all dynamically allocated service users. (See the
DynamicUser= setting in unit files.)
To make use of these NSS modules, please add them to the "hosts:", To make use of these NSS modules, please add them to the "hosts:",
"passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve" "passwd:" and "group:" lines in /etc/nsswitch.conf. The "resolve"
@ -283,8 +283,8 @@ NSS:
The four modules should be used in the following order: The four modules should be used in the following order:
passwd: compat systemd passwd: compat mymachines systemd
group: compat systemd group: compat mymachines systemd
hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname
SYSV INIT.D SCRIPTS: SYSV INIT.D SCRIPTS:

1
TODO
View File

@ -336,6 +336,7 @@ Features:
* homed: * homed:
- when user tries to log into record signed by unrecognized key, automatically add key to our chain after polkit auth - when user tries to log into record signed by unrecognized key, automatically add key to our chain after polkit auth
- hook up machined/nspawn users with a varlink user query interface
- rollback when resize fails mid-operation - rollback when resize fails mid-operation
- GNOME's side for forget key on suspend (requires rework so that lock screen runs outside of uid) - GNOME's side for forget key on suspend (requires rework so that lock screen runs outside of uid)
- resize on login? - resize on login?

View File

@ -132,7 +132,7 @@ but downstreams are strongly advised against doing that.)
range is above the 16bit boundary. Moreover it's below the 31bit boundary, range is above the 16bit boundary. Moreover it's below the 31bit boundary,
as some broken code (specifically: the kernel's `devpts` file system) as some broken code (specifically: the kernel's `devpts` file system)
erroneously considers UIDs signed integers, and hence can't deal with values erroneously considers UIDs signed integers, and hence can't deal with values
above 2^31. The `systemd-machined.service` service will synthesize user above 2^31. The `nss-mymachines` glibc NSS module will synthesize user
database records for all UIDs assigned to a running container from this database records for all UIDs assigned to a running container from this
range. range.
@ -240,14 +240,14 @@ the artifacts the container manager persistently leaves in the system.
| 5 | `tty` group | `systemd` | `/etc/passwd` | | 5 | `tty` group | `systemd` | `/etc/passwd` |
| 6…999 | System users | Distributions | `/etc/passwd` | | 6…999 | System users | Distributions | `/etc/passwd` |
| 1000…60000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… | | 1000…60000 | Regular users | Distributions | `/etc/passwd` + LDAP/NIS/… |
| 60001…60513 | Human Users (homed) | `systemd` | `nss-systemd` | | 60001…60513 | Human Users (homed) | `systemd` | `nss-systemd`
| 60514…61183 | Unused | | | | 60514…61183 | Unused | | |
| 61184…65519 | Dynamic service users | `systemd` | `nss-systemd` | | 61184…65519 | Dynamic service users | `systemd` | `nss-systemd` |
| 65520…65533 | Unused | | | | 65520…65533 | Unused | | |
| 65534 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` | | 65534 | `nobody` user | Linux | `/etc/passwd` + `nss-systemd` |
| 65535 | 16bit `(uid_t) -1` | Linux | | | 65535 | 16bit `(uid_t) -1` | Linux | |
| 65536…524287 | Unused | | | | 65536…524287 | Unused | | |
| 524288…1879048191 | Container UID ranges | `systemd` | `nss-systemd` | | 524288…1879048191 | Container UID ranges | `systemd` | `nss-mymachines` |
| 1879048192…2147483647 | Unused | | | | 1879048192…2147483647 | Unused | | |
| 2147483648…4294967294 | HIC SVNT LEONES | | | | 2147483648…4294967294 | HIC SVNT LEONES | | |
| 4294967295 | 32bit `(uid_t) -1` | Linux | | | 4294967295 | 32bit `(uid_t) -1` | Linux | |

View File

@ -108,7 +108,7 @@ example, introspection is not available, and the resolver logic is not used.
## Other Services ## Other Services
The `systemd` project provides three other services implementing this The `systemd` project provides two other services implementing this
interface. Specifically: interface. Specifically:
1. `io.systemd.DynamicUser` → This service is implemented by the service 1. `io.systemd.DynamicUser` → This service is implemented by the service
@ -119,10 +119,6 @@ interface. Specifically:
and provides records for the users and groups defined by the home and provides records for the users and groups defined by the home
directories it manages. directories it manages.
3. `io.systemd.Machine` → This service is implemented by
`systemd-machined.service` and provides records for the users and groups used
by local containers that use user namespacing.
Other projects are invited to implement these services too. For example it Other projects are invited to implement these services too. For example it
would make sense for LDAP/ActiveDirectory projects to implement these would make sense for LDAP/ActiveDirectory projects to implement these
interfaces, which would provide them a way to do per-user resource management interfaces, which would provide them a way to do per-user resource management
@ -189,7 +185,6 @@ error NoRecordFound()
error BadService() error BadService()
error ServiceNotAvailable() error ServiceNotAvailable()
error ConflictingRecordFound() error ConflictingRecordFound()
error EnumerationNotSupported()
``` ```
The `GetUserRecord` method looks up or enumerates a user record. If the `uid` The `GetUserRecord` method looks up or enumerates a user record. If the `uid`
@ -269,11 +264,4 @@ services. Result of this is that it can be one service that defines a user A,
and another service that defines a group B, and a third service that declares and another service that defines a group B, and a third service that declares
that A is a member of B. that A is a member of B.
Looking up explicit users/groups by their name or UID/GID, or querying
user/group memberships must be supported by all services implementing these
interfaces. However, supporting enumeration (i.e. user/group lookups that may
result in more than one reply, because neither UID/GID nor name is specified)
is optional. Services which are asked for enumeration may return the
`EnumerationNotSupported` error in this case.
And that's really all there is to it. And that's really all there is to it.

View File

@ -1,7 +1,7 @@
# This file is part of systemd. # This file is part of systemd.
passwd: compat systemd passwd: compat mymachines systemd
group: compat [SUCCESS=merge] systemd group: compat [SUCCESS=merge] mymachines [SUCCESS=merge] systemd
shadow: compat shadow: compat
hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname hosts: files mymachines resolve [!UNAVAIL=return] dns myhostname

View File

@ -82,8 +82,8 @@
<command>nss-myhostname</command> correctly:</para> <command>nss-myhostname</command> correctly:</para>
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat mymachines systemd
group: compat systemd group: compat mymachines systemd
shadow: compat shadow: compat
# Either (untrusted network): # Either (untrusted network):

View File

@ -39,13 +39,22 @@
Note that the name that is resolved is the one registered with <command>systemd-machined</command>, which Note that the name that is resolved is the one registered with <command>systemd-machined</command>, which
may be different than the hostname configured inside of the container.</para> may be different than the hostname configured inside of the container.</para>
<para>To activate the NSS module, add <literal>mymachines</literal> to the line starting with <para>The module also provides name resolution for user and group identifiers mapped to containers. All names from
<literal>hosts:</literal> in <filename>/etc/nsswitch.conf</filename>.</para> the range allocated to a given container <replaceable>container</replaceable> are exposed on the host as
<literal>vu-<replaceable>container</replaceable>-<replaceable>uid</replaceable></literal> and
<literal>vg-<replaceable>container</replaceable>-<replaceable>gid</replaceable></literal> (see example below). This
functionality only applies to containers using user namespacing (see the description of
<option>--private-users</option> in
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para>
<para>To activate the NSS module, add <literal>mymachines</literal> to the lines starting with
<literal>hosts:</literal>, <literal>passwd:</literal> and <literal>group:</literal> in
<filename>/etc/nsswitch.conf</filename>.</para>
<para>It is recommended to place <literal>mymachines</literal> after the <literal>files</literal> or <para>It is recommended to place <literal>mymachines</literal> after the <literal>files</literal> or
<literal>compat</literal> entry of the <filename>/etc/nsswitch.conf</filename> line to make sure that its <literal>compat</literal> entry of the <filename>/etc/nsswitch.conf</filename> lines to make sure that its mappings
mappings are preferred over other resolvers such as DNS, but so that <filename>/etc/hosts</filename> are preferred over other resolvers such as DNS, but so that <filename>/etc/hosts</filename>,
based mappings take precedence.</para> <filename>/etc/passwd</filename> and <filename>/etc/group</filename> based mappings take precedence.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
@ -55,8 +64,8 @@
<command>nss-mymachines</command> correctly:</para> <command>nss-mymachines</command> correctly:</para>
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat <command>mymachines</command> systemd
group: compat systemd group: compat <command>mymachines</command> systemd
shadow: compat shadow: compat
hosts: <command>mymachines</command> resolve [!UNAVAIL=return] myhostname files dns hosts: <command>mymachines</command> resolve [!UNAVAIL=return] myhostname files dns
@ -72,7 +81,7 @@ netgroup: nis</programlisting>
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Example: Mappings provided by <filename>nss-mymachines</filename></title> <title>Mappings provided by <filename>nss-mymachines</filename></title>
<para>The container <literal>rawhide</literal> is spawned using <para>The container <literal>rawhide</literal> is spawned using
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>: <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>:
@ -87,6 +96,29 @@ $ machinectl --max-addresses=3
MACHINE CLASS SERVICE OS VERSION ADDRESSES MACHINE CLASS SERVICE OS VERSION ADDRESSES
rawhide container systemd-nspawn fedora 30 169.254.40.164 fe80::94aa:3aff:fe7b:d4b9 rawhide container systemd-nspawn fedora 30 169.254.40.164 fe80::94aa:3aff:fe7b:d4b9
$ getent passwd vu-rawhide-0 vu-rawhide-81
vu-rawhide-0:*:20119552:65534:vu-rawhide-0:/:/usr/sbin/nologin
vu-rawhide-81:*:20119633:65534:vu-rawhide-81:/:/usr/sbin/nologin
$ getent group vg-rawhide-0 vg-rawhide-81
vg-rawhide-0:*:20119552:
vg-rawhide-81:*:20119633:
$ ps -o user:15,pid,tty,command -e|grep '^vu-rawhide'
vu-rawhide-0 692 ? /usr/lib/systemd/systemd
vu-rawhide-0 731 ? /usr/lib/systemd/systemd-journald
vu-rawhide-192 734 ? /usr/lib/systemd/systemd-networkd
vu-rawhide-193 738 ? /usr/lib/systemd/systemd-resolved
vu-rawhide-0 742 ? /usr/lib/systemd/systemd-logind
vu-rawhide-81 744 ? /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
vu-rawhide-0 746 ? /usr/sbin/sshd -D ...
vu-rawhide-0 752 ? /usr/lib/systemd/systemd --user
vu-rawhide-0 753 ? (sd-pam)
vu-rawhide-0 1628 ? login -- zbyszek
vu-rawhide-1000 1630 ? /usr/lib/systemd/systemd --user
vu-rawhide-1000 1631 ? (sd-pam)
vu-rawhide-1000 1637 pts/8 -zsh
$ ping -c1 rawhide $ ping -c1 rawhide
PING rawhide(fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide)) 56 data bytes PING rawhide(fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide)) 56 data bytes
64 bytes from fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide): icmp_seq=1 ttl=64 time=0.045 ms 64 bytes from fe80::94aa:3aff:fe7b:d4b9%ve-rawhide (fe80::94aa:3aff:fe7b:d4b9%ve-rawhide): icmp_seq=1 ttl=64 time=0.045 ms

View File

@ -63,8 +63,8 @@
correctly:</para> correctly:</para>
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat systemd <programlisting>passwd: compat mymachines systemd
group: compat systemd group: compat mymachines systemd
shadow: compat shadow: compat
hosts: mymachines <command>resolve [!UNAVAIL=return]</command> myhostname files dns hosts: mymachines <command>resolve [!UNAVAIL=return]</command> myhostname files dns

View File

@ -35,8 +35,8 @@
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> (for its <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> (for its
<varname>DynamicUser=</varname> feature, see <varname>DynamicUser=</varname> feature, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details), details) or
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>, or <citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para> <citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
<para>This module also ensures that the root and nobody users and groups (i.e. the users/groups with the UIDs/GIDs <para>This module also ensures that the root and nobody users and groups (i.e. the users/groups with the UIDs/GIDs
0 and 65534) remain resolvable at all times, even if they aren't listed in <filename>/etc/passwd</filename> or 0 and 65534) remain resolvable at all times, even if they aren't listed in <filename>/etc/passwd</filename> or
@ -55,14 +55,14 @@
</refsect1> </refsect1>
<refsect1> <refsect1>
<title>Configuration in <filename>/etc/nsswitch.conf</filename></title> <title>Example</title>
<para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables <para>Here is an example <filename>/etc/nsswitch.conf</filename> file that enables
<command>nss-systemd</command> correctly:</para> <command>nss-systemd</command> correctly:</para>
<!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf --> <!-- synchronize with other nss-* man pages and factory/etc/nsswitch.conf -->
<programlisting>passwd: compat <command>systemd</command> <programlisting>passwd: compat mymachines <command>systemd</command>
group: compat [SUCCESS=merge] <command>systemd</command> group: compat [SUCCESS=merge] mymachines [SUCCESS=merge] <command>systemd</command>
shadow: compat shadow: compat
hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns hosts: mymachines resolve [!UNAVAIL=return] myhostname files dns
@ -77,47 +77,6 @@ netgroup: nis</programlisting>
</refsect1> </refsect1>
<refsect1>
<title>Example: Mappings provided by <filename>systemd-machined.service</filename></title>
<para>The container <literal>rawhide</literal> is spawned using
<citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>:
</para>
<programlisting># systemd-nspawn -M rawhide --boot --network-veth --private-users=pick
Spawning container rawhide on /var/lib/machines/rawhide.
Selected user namespace base 20119552 and range 65536.
...
$ machinectl --max-addresses=3
MACHINE CLASS SERVICE OS VERSION ADDRESSES
rawhide container systemd-nspawn fedora 30 169.254.40.164 fe80::94aa:3aff:fe7b:d4b9
$ getent passwd vu-rawhide-0 vu-rawhide-81
vu-rawhide-0:*:20119552:65534:vu-rawhide-0:/:/usr/sbin/nologin
vu-rawhide-81:*:20119633:65534:vu-rawhide-81:/:/usr/sbin/nologin
$ getent group vg-rawhide-0 vg-rawhide-81
vg-rawhide-0:*:20119552:
vg-rawhide-81:*:20119633:
$ ps -o user:15,pid,tty,command -e|grep '^vu-rawhide'
vu-rawhide-0 692 ? /usr/lib/systemd/systemd
vu-rawhide-0 731 ? /usr/lib/systemd/systemd-journald
vu-rawhide-192 734 ? /usr/lib/systemd/systemd-networkd
vu-rawhide-193 738 ? /usr/lib/systemd/systemd-resolved
vu-rawhide-0 742 ? /usr/lib/systemd/systemd-logind
vu-rawhide-81 744 ? /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
vu-rawhide-0 746 ? /usr/sbin/sshd -D ...
vu-rawhide-0 752 ? /usr/lib/systemd/systemd --user
vu-rawhide-0 753 ? (sd-pam)
vu-rawhide-0 1628 ? login -- zbyszek
vu-rawhide-1000 1630 ? /usr/lib/systemd/systemd --user
vu-rawhide-1000 1631 ? (sd-pam)
vu-rawhide-1000 1637 pts/8 -zsh
</programlisting>
</refsect1>
<refsect1> <refsect1>
<title>See Also</title> <title>See Also</title>
<para> <para>
@ -126,9 +85,6 @@ vu-rawhide-1000 1637 pts/8 -zsh
<citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>nss-resolve</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>nss-myhostname</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>, <citerefentry><refentrytitle>nss-mymachines</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-userdbd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-homed.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>nsswitch.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry project='man-pages'><refentrytitle>getent</refentrytitle><manvolnum>1</manvolnum></citerefentry> <citerefentry project='man-pages'><refentrytitle>getent</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para> </para>

View File

@ -167,7 +167,6 @@
<varlistentry> <varlistentry>
<term><keycap>h</keycap></term> <term><keycap>h</keycap></term>
<term><keycap>?</keycap></term> <term><keycap>?</keycap></term>
<term><keycap>F1</keycap></term>
<listitem><para>Show a help screen</para></listitem> <listitem><para>Show a help screen</para></listitem>
</varlistentry> </varlistentry>

View File

@ -116,13 +116,6 @@
<citerefentry><refentrytitle>systemd-importd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> <citerefentry><refentrytitle>systemd-importd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
is also available, which implements importing, exporting, and downloading of container and VM images. is also available, which implements importing, exporting, and downloading of container and VM images.
</para> </para>
<para>For each container registered with <filename>systemd-machined.service</filename> that employs user
namespacing, users/groups are synthesized for the used UIDs/GIDs. These are made available to the system
using the <ulink url="https://systemd.io/USER_GROUP_API">User/Group Record Lookup API via
Varlink</ulink>, and thus may be resolved with
<citerefentry><refentrytitle>userdbctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> or the
usual glibc NSS calls.</para>
</refsect1> </refsect1>
<refsect1> <refsect1>

View File

@ -186,15 +186,6 @@
available to the system.</para></listitem> available to the system.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><constant>io.systemd.Machine</constant></term>
<listitem><para>This service is provided by
<citerefentry><refentrytitle>systemd-machined.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
and synthesizes records for all users/groups used by a container that employs user
namespacing.</para></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><constant>io.systemd.Multiplexer</constant></term> <term><constant>io.systemd.Multiplexer</constant></term>

View File

@ -20,16 +20,14 @@
#define procfs_file_alloca(pid, field) \ #define procfs_file_alloca(pid, field) \
({ \ ({ \
pid_t _pid_ = (pid); \ pid_t _pid_ = (pid); \
const char *_field_ = (field); \ const char *_r_; \
char *_r_; \
if (_pid_ == 0) { \ if (_pid_ == 0) { \
_r_ = newa(char, STRLEN("/proc/self/") + strlen(_field_) + 1); \ _r_ = ("/proc/self/" field); \
strcpy(stpcpy(_r_, "/proc/self/"), _field_); \
} else { \ } else { \
_r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + strlen(_field_) + 1); \ _r_ = newa(char, STRLEN("/proc/") + DECIMAL_STR_MAX(pid_t) + 1 + sizeof(field)); \
sprintf(_r_, "/proc/" PID_FMT "/%s", _pid_, _field_); \ sprintf((char*) _r_, "/proc/"PID_FMT"/" field, _pid_); \
} \ } \
(const char*) _r_; \ _r_; \
}) })
typedef enum ProcessCmdlineFlags { typedef enum ProcessCmdlineFlags {

View File

@ -346,7 +346,6 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
bool found_monotonic = false, found_realtime = false; bool found_monotonic = false, found_realtime = false;
bool leave_around = false; bool leave_around = false;
triple_timestamp ts; triple_timestamp ts;
dual_timestamp dts;
TimerValue *v; TimerValue *v;
Unit *trigger; Unit *trigger;
int r; int r;
@ -390,10 +389,10 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
/* To make the delay due to RandomizedDelaySec= work even at boot, /* To make the delay due to RandomizedDelaySec= work even at boot,
* if the scheduled time has already passed, set the time when systemd * if the scheduled time has already passed, set the time when systemd
* first started as the scheduled time. */ * first started as the scheduled time.
dual_timestamp_from_monotonic(&dts, UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic); * Also, we don't have to check t->persistent since the logic implicitly express true. */
if (v->next_elapse < dts.realtime) if (v->next_elapse < UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime)
v->next_elapse = dts.realtime; v->next_elapse = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].realtime;
if (!found_realtime) if (!found_realtime)
t->next_elapse_realtime = v->next_elapse; t->next_elapse_realtime = v->next_elapse;

View File

@ -746,143 +746,6 @@ int machine_get_uid_shift(Machine *m, uid_t *ret) {
return 0; return 0;
} }
static int machine_owns_uid_internal(
Machine *machine,
const char *map_file, /* "uid_map" or "gid_map" */
uid_t uid,
uid_t *ret_internal_uid) {
_cleanup_fclose_ FILE *f = NULL;
const char *p;
/* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
assert_cc(sizeof(uid_t) == sizeof(gid_t));
assert(machine);
/* Checks if the specified host UID is owned by the machine, and returns the UID it maps to
* internally in the machine */
if (machine->class != MACHINE_CONTAINER)
goto negative;
p = procfs_file_alloca(machine->leader, map_file);
f = fopen(p, "re");
if (!f) {
log_debug_errno(errno, "Failed to open %s, ignoring.", p);
goto negative;
}
for (;;) {
uid_t uid_base, uid_shift, uid_range, converted;
int k;
errno = 0;
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
/* The private user namespace is disabled, ignoring. */
if (uid_shift == 0)
continue;
if (uid < uid_shift || uid >= uid_shift + uid_range)
continue;
converted = (uid - uid_shift + uid_base);
if (!uid_is_valid(converted))
return -EINVAL;
if (ret_internal_uid)
*ret_internal_uid = converted;
return true;
}
negative:
if (ret_internal_uid)
*ret_internal_uid = UID_INVALID;
return false;
}
int machine_owns_uid(Machine *machine, uid_t uid, uid_t *ret_internal_uid) {
return machine_owns_uid_internal(machine, "uid_map", uid, ret_internal_uid);
}
int machine_owns_gid(Machine *machine, gid_t gid, gid_t *ret_internal_gid) {
return machine_owns_uid_internal(machine, "gid_map", (uid_t) gid, (uid_t*) ret_internal_gid);
}
static int machine_translate_uid_internal(
Machine *machine,
const char *map_file, /* "uid_map" or "gid_map" */
uid_t uid,
uid_t *ret_host_uid) {
_cleanup_fclose_ FILE *f = NULL;
const char *p;
/* This is a generic implementation for both uids and gids, under the assumptions they have the same types and semantics. */
assert_cc(sizeof(uid_t) == sizeof(gid_t));
assert(machine);
assert(uid_is_valid(uid));
if (machine->class != MACHINE_CONTAINER)
return -ESRCH;
/* Translates a machine UID into a host UID */
p = procfs_file_alloca(machine->leader, map_file);
f = fopen(p, "re");
if (!f)
return -errno;
for (;;) {
uid_t uid_base, uid_shift, uid_range, converted;
int k;
errno = 0;
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
if (uid < uid_base || uid >= uid_base + uid_range)
continue;
converted = uid - uid_base + uid_shift;
if (!uid_is_valid(converted))
return -EINVAL;
if (ret_host_uid)
*ret_host_uid = converted;
return 0;
}
return -ESRCH;
}
int machine_translate_uid(Machine *machine, gid_t uid, gid_t *ret_host_uid) {
return machine_translate_uid_internal(machine, "uid_map", uid, ret_host_uid);
}
int machine_translate_gid(Machine *machine, gid_t gid, gid_t *ret_host_gid) {
return machine_translate_uid_internal(machine, "gid_map", (uid_t) gid, (uid_t*) ret_host_gid);
}
static const char* const machine_class_table[_MACHINE_CLASS_MAX] = { static const char* const machine_class_table[_MACHINE_CLASS_MAX] = {
[MACHINE_CONTAINER] = "container", [MACHINE_CONTAINER] = "container",
[MACHINE_VM] = "vm", [MACHINE_VM] = "vm",

View File

@ -94,9 +94,3 @@ int machine_openpt(Machine *m, int flags, char **ret_slave);
int machine_open_terminal(Machine *m, const char *path, int mode); int machine_open_terminal(Machine *m, const char *path, int mode);
int machine_get_uid_shift(Machine *m, uid_t *ret); int machine_get_uid_shift(Machine *m, uid_t *ret);
int machine_owns_uid(Machine *m, uid_t host_uid, uid_t *ret_internal_uid);
int machine_owns_gid(Machine *m, gid_t host_gid, gid_t *ret_internal_gid);
int machine_translate_uid(Machine *m, uid_t internal_uid, uid_t *ret_host_uid);
int machine_translate_gid(Machine *m, gid_t internal_gid, gid_t *ret_host_gid);

View File

@ -3,7 +3,6 @@
#include "machined.h" #include "machined.h"
#include "nscd-flush.h" #include "nscd-flush.h"
#include "strv.h" #include "strv.h"
#include "user-util.h"
static int on_nscd_cache_flush_event(sd_event_source *s, void *userdata) { static int on_nscd_cache_flush_event(sd_event_source *s, void *userdata) {
/* Let's ask glibc's nscd daemon to flush its caches. We request this for the three database machines may show /* Let's ask glibc's nscd daemon to flush its caches. We request this for the three database machines may show
@ -35,72 +34,3 @@ int manager_enqueue_nscd_cache_flush(Manager *m) {
return 0; return 0;
} }
int manager_find_machine_for_uid(Manager *m, uid_t uid, Machine **ret_machine, uid_t *ret_internal_uid) {
Machine *machine;
Iterator i;
int r;
assert(m);
assert(uid_is_valid(uid));
/* Finds the machine for the specified host UID and returns it along with the UID translated into the
* internal UID inside the machine */
HASHMAP_FOREACH(machine, m->machines, i) {
uid_t converted;
r = machine_owns_uid(machine, uid, &converted);
if (r < 0)
return r;
if (r) {
if (ret_machine)
*ret_machine = machine;
if (ret_internal_uid)
*ret_internal_uid = converted;
return true;
}
}
if (ret_machine)
*ret_machine = NULL;
if (ret_internal_uid)
*ret_internal_uid = UID_INVALID;
return false;
}
int manager_find_machine_for_gid(Manager *m, gid_t gid, Machine **ret_machine, gid_t *ret_internal_gid) {
Machine *machine;
Iterator i;
int r;
assert(m);
assert(gid_is_valid(gid));
HASHMAP_FOREACH(machine, m->machines, i) {
gid_t converted;
r = machine_owns_gid(machine, gid, &converted);
if (r < 0)
return r;
if (r) {
if (ret_machine)
*ret_machine = machine;
if (ret_internal_gid)
*ret_internal_gid = converted;
return true;
}
}
if (ret_machine)
*ret_machine = NULL;
if (ret_internal_gid)
*ret_internal_gid = GID_INVALID;
return false;
}

View File

@ -883,11 +883,11 @@ static int method_set_image_limit(sd_bus_message *message, void *userdata, sd_bu
} }
static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int method_map_from_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_fclose_ FILE *f = NULL;
Manager *m = userdata; Manager *m = userdata;
const char *name; const char *name, *p;
Machine *machine; Machine *machine;
uint32_t uid; uint32_t uid;
uid_t converted;
int r; int r;
r = sd_bus_message_read(message, "su", &name, &uid); r = sd_bus_message_read(message, "su", &name, &uid);
@ -904,20 +904,44 @@ static int method_map_from_machine_user(sd_bus_message *message, void *userdata,
if (machine->class != MACHINE_CONTAINER) if (machine->class != MACHINE_CONTAINER)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
r = machine_translate_uid(machine, uid, &converted); p = procfs_file_alloca(machine->leader, "uid_map");
if (r == -ESRCH) f = fopen(p, "re");
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name); if (!f)
if (r < 0) return -errno;
return r;
return sd_bus_reply_method_return(message, "u", (uint32_t) converted); for (;;) {
uid_t uid_base, uid_shift, uid_range, converted;
int k;
errno = 0;
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
if (uid < uid_base || uid >= uid_base + uid_range)
continue;
converted = uid - uid_base + uid_shift;
if (!uid_is_valid(converted))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
}
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching user mappings.", name);
} }
static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int method_map_to_machine_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *o = NULL;
Manager *m = userdata; Manager *m = userdata;
Machine *machine; Machine *machine;
uid_t uid, converted; uid_t uid;
Iterator i;
int r; int r;
r = sd_bus_message_read(message, "u", &uid); r = sd_bus_message_read(message, "u", &uid);
@ -928,24 +952,63 @@ static int method_map_to_machine_user(sd_bus_message *message, void *userdata, s
if (uid < 0x10000) if (uid < 0x10000)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid); return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "User " UID_FMT " belongs to host UID range", uid);
r = manager_find_machine_for_uid(m, uid, &machine, &converted); HASHMAP_FOREACH(machine, m->machines, i) {
if (r < 0) _cleanup_fclose_ FILE *f = NULL;
return r; char p[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t) + 1];
if (!r)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
o = machine_bus_path(machine); if (machine->class != MACHINE_CONTAINER)
if (!o) continue;
return -ENOMEM;
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); xsprintf(p, "/proc/" UID_FMT "/uid_map", machine->leader);
f = fopen(p, "re");
if (!f) {
log_warning_errno(errno, "Failed to open %s, ignoring,", p);
continue;
}
for (;;) {
_cleanup_free_ char *o = NULL;
uid_t uid_base, uid_shift, uid_range, converted;
int k;
errno = 0;
k = fscanf(f, UID_FMT " " UID_FMT " " UID_FMT, &uid_base, &uid_shift, &uid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
/* The private user namespace is disabled, ignoring. */
if (uid_shift == 0)
continue;
if (uid < uid_shift || uid >= uid_shift + uid_range)
continue;
converted = (uid - uid_shift + uid_base);
if (!uid_is_valid(converted))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user ID " UID_FMT, uid);
o = machine_bus_path(machine);
if (!o)
return -ENOMEM;
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
}
}
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "No matching user mapping for " UID_FMT ".", uid);
} }
static int method_map_from_machine_group(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int method_map_from_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
Manager *m = userdata; _cleanup_fclose_ FILE *f = NULL;
const char *name; Manager *m = groupdata;
const char *name, *p;
Machine *machine; Machine *machine;
gid_t converted;
uint32_t gid; uint32_t gid;
int r; int r;
@ -963,20 +1026,44 @@ static int method_map_from_machine_group(sd_bus_message *message, void *userdata
if (machine->class != MACHINE_CONTAINER) if (machine->class != MACHINE_CONTAINER)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not supported for non-container machines.");
r = machine_translate_gid(machine, gid, &converted); p = procfs_file_alloca(machine->leader, "gid_map");
if (r == -ESRCH) f = fopen(p, "re");
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER_MAPPING, "Machine '%s' has no matching group mappings.", name); if (!f)
if (r < 0) return -errno;
return r;
return sd_bus_reply_method_return(message, "u", (uint32_t) converted); for (;;) {
gid_t gid_base, gid_shift, gid_range, converted;
int k;
errno = 0;
k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
if (gid < gid_base || gid >= gid_base + gid_range)
continue;
converted = gid - gid_base + gid_shift;
if (!gid_is_valid(converted))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
return sd_bus_reply_method_return(message, "u", (uint32_t) converted);
}
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Machine '%s' has no matching group mappings.", name);
} }
static int method_map_to_machine_group(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int method_map_to_machine_group(sd_bus_message *message, void *groupdata, sd_bus_error *error) {
_cleanup_free_ char *o = NULL; Manager *m = groupdata;
Manager *m = userdata;
Machine *machine; Machine *machine;
gid_t gid, converted; gid_t gid;
Iterator i;
int r; int r;
r = sd_bus_message_read(message, "u", &gid); r = sd_bus_message_read(message, "u", &gid);
@ -987,17 +1074,56 @@ static int method_map_to_machine_group(sd_bus_message *message, void *userdata,
if (gid < 0x10000) if (gid < 0x10000)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid); return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "Group " GID_FMT " belongs to host GID range", gid);
r = manager_find_machine_for_gid(m, gid, &machine, &converted); HASHMAP_FOREACH(machine, m->machines, i) {
if (r < 0) _cleanup_fclose_ FILE *f = NULL;
return r; char p[STRLEN("/proc//gid_map") + DECIMAL_STR_MAX(pid_t) + 1];
if (!r)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
o = machine_bus_path(machine); if (machine->class != MACHINE_CONTAINER)
if (!o) continue;
return -ENOMEM;
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted); xsprintf(p, "/proc/" GID_FMT "/gid_map", machine->leader);
f = fopen(p, "re");
if (!f) {
log_warning_errno(errno, "Failed to open %s, ignoring,", p);
continue;
}
for (;;) {
_cleanup_free_ char *o = NULL;
gid_t gid_base, gid_shift, gid_range, converted;
int k;
errno = 0;
k = fscanf(f, GID_FMT " " GID_FMT " " GID_FMT, &gid_base, &gid_shift, &gid_range);
if (k < 0 && feof(f))
break;
if (k != 3) {
if (ferror(f))
return errno_or_else(EIO);
return -EIO;
}
/* The private user namespace is disabled, ignoring. */
if (gid_shift == 0)
continue;
if (gid < gid_shift || gid >= gid_shift + gid_range)
continue;
converted = (gid - gid_shift + gid_base);
if (!gid_is_valid(converted))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group ID " GID_FMT, gid);
o = machine_bus_path(machine);
if (!o)
return -ENOMEM;
return sd_bus_reply_method_return(message, "sou", machine->name, o, (uint32_t) converted);
}
}
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_GROUP_MAPPING, "No matching group mapping for " GID_FMT ".", gid);
} }
const sd_bus_vtable manager_vtable[] = { const sd_bus_vtable manager_vtable[] = {

View File

@ -1,404 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "format-util.h"
#include "machined-varlink.h"
#include "mkdir.h"
#include "user-util.h"
#include "varlink.h"
typedef struct LookupParameters {
const char *user_name;
const char *group_name;
union {
uid_t uid;
gid_t gid;
};
const char *service;
} LookupParameters;
static int build_user_json(const char *user_name, uid_t uid, const char *real_name, JsonVariant **ret) {
assert(user_name);
assert(uid_is_valid(uid));
assert(ret);
return json_build(ret, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("record", JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("userName", JSON_BUILD_STRING(user_name)),
JSON_BUILD_PAIR("uid", JSON_BUILD_UNSIGNED(uid)),
JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(GID_NOBODY)),
JSON_BUILD_PAIR_CONDITION(!isempty(real_name), "realName", JSON_BUILD_STRING(real_name)),
JSON_BUILD_PAIR("homeDirectory", JSON_BUILD_STRING("/")),
JSON_BUILD_PAIR("shell", JSON_BUILD_STRING(NOLOGIN)),
JSON_BUILD_PAIR("locked", JSON_BUILD_BOOLEAN(true)),
JSON_BUILD_PAIR("service", JSON_BUILD_STRING("io.systemd.Machine")),
JSON_BUILD_PAIR("disposition", JSON_BUILD_STRING("container"))))));
}
static bool user_match_lookup_parameters(LookupParameters *p, const char *name, uid_t uid) {
assert(p);
if (p->user_name && !streq(name, p->user_name))
return false;
if (uid_is_valid(p->uid) && uid != p->uid)
return false;
return true;
}
static int user_lookup_uid(Manager *m, uid_t uid, char **ret_name, char **ret_real_name) {
_cleanup_free_ char *n = NULL, *rn = NULL;
uid_t converted_uid;
Machine *machine;
int r;
assert(m);
assert(uid_is_valid(uid));
assert(ret_name);
assert(ret_real_name);
if (uid < 0x10000) /* Host UID range */
return -ESRCH;
r = manager_find_machine_for_uid(m, uid, &machine, &converted_uid);
if (r < 0)
return r;
if (!r)
return -ESRCH;
if (asprintf(&n, "vu-%s-" UID_FMT, machine->name, converted_uid) < 0)
return -ENOMEM;
/* Don't synthesize invalid user/group names (too long...) */
if (!valid_user_group_name(n, 0))
return -ESRCH;
if (asprintf(&rn, "UID " UID_FMT " of Container %s", converted_uid, machine->name) < 0)
return -ENOMEM;
/* Don't synthesize invalid real names either, but since this field doesn't matter much, simply invalidate things */
if (!valid_gecos(rn))
rn = mfree(rn);
*ret_name = TAKE_PTR(n);
*ret_real_name = TAKE_PTR(rn);
return 0;
}
static int user_lookup_name(Manager *m, const char *name, uid_t *ret_uid, char **ret_real_name) {
_cleanup_free_ char *mn = NULL, *rn = NULL;
uid_t uid, converted_uid;
Machine *machine;
const char *e, *d;
int r;
assert(m);
if (!valid_user_group_name(name, 0))
return -ESRCH;
e = startswith(name, "vu-");
if (!e)
return -ESRCH;
d = strrchr(e, '-');
if (!d)
return -ESRCH;
if (parse_uid(d + 1, &uid) < 0)
return -ESRCH;
mn = strndup(e, d - e);
if (!mn)
return -ENOMEM;
machine = hashmap_get(m->machines, mn);
if (!machine)
return -ESRCH;
if (machine->class != MACHINE_CONTAINER)
return -ESRCH;
r = machine_translate_uid(machine, uid, &converted_uid);
if (r < 0)
return r;
if (asprintf(&rn, "UID " UID_FMT " of Container %s", uid, machine->name) < 0)
return -ENOMEM;
if (!valid_gecos(rn))
rn = mfree(rn);
*ret_uid = converted_uid;
*ret_real_name = TAKE_PTR(rn);
return 0;
}
static int vl_method_get_user_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
{ "uid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(LookupParameters, uid), 0 },
{ "userName", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, user_name), JSON_SAFE },
{ "service", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
{}
};
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
LookupParameters p = {
.uid = UID_INVALID,
};
_cleanup_free_ char *found_name = NULL, *found_real_name = NULL;
uid_t found_uid = UID_INVALID, uid;
Manager *m = userdata;
const char *un;
int r;
assert(parameters);
assert(m);
r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
if (r < 0)
return r;
if (!streq_ptr(p.service, "io.systemd.Machine"))
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
if (uid_is_valid(p.uid))
r = user_lookup_uid(m, p.uid, &found_name, &found_real_name);
else if (p.user_name)
r = user_lookup_name(m, p.user_name, &found_uid, &found_real_name);
else
return varlink_error(link, "io.systemd.UserDatabase.EnumerationNotSupported", NULL);
if (r == -ESRCH)
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
if (r < 0)
return r;
uid = uid_is_valid(found_uid) ? found_uid : p.uid;
un = found_name ?: p.user_name;
if (!user_match_lookup_parameters(&p, un, uid))
return varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL);
r = build_user_json(un, uid, found_real_name, &v);
if (r < 0)
return r;
return varlink_reply(link, v);
}
static int build_group_json(const char *group_name, gid_t gid, JsonVariant **ret) {
assert(group_name);
assert(gid_is_valid(gid));
assert(ret);
return json_build(ret, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("record", JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("groupName", JSON_BUILD_STRING(group_name)),
JSON_BUILD_PAIR("gid", JSON_BUILD_UNSIGNED(gid)),
JSON_BUILD_PAIR("service", JSON_BUILD_STRING("io.systemd.Machine")),
JSON_BUILD_PAIR("disposition", JSON_BUILD_STRING("container"))))));
}
static bool group_match_lookup_parameters(LookupParameters *p, const char *name, gid_t gid) {
assert(p);
if (p->group_name && !streq(name, p->group_name))
return false;
if (gid_is_valid(p->gid) && gid != p->gid)
return false;
return true;
}
static int group_lookup_gid(Manager *m, gid_t gid, char **ret_name) {
_cleanup_free_ char *n = NULL;
gid_t converted_gid;
Machine *machine;
int r;
assert(m);
assert(gid_is_valid(gid));
assert(ret_name);
if (gid < 0x10000) /* Host GID range */
return -ESRCH;
r = manager_find_machine_for_gid(m, gid, &machine, &converted_gid);
if (r < 0)
return r;
if (!r)
return -ESRCH;
if (asprintf(&n, "vg-%s-" GID_FMT, machine->name, converted_gid) < 0)
return -ENOMEM;
if (!valid_user_group_name(n, 0))
return -ESRCH;
*ret_name = TAKE_PTR(n);
return 0;
}
static int group_lookup_name(Manager *m, const char *name, gid_t *ret_gid) {
_cleanup_free_ char *mn = NULL;
gid_t gid, converted_gid;
Machine *machine;
const char *e, *d;
int r;
assert(m);
if (!valid_user_group_name(name, 0))
return -ESRCH;
e = startswith(name, "vg-");
if (!e)
return -ESRCH;
d = strrchr(e, '-');
if (!d)
return -ESRCH;
if (parse_gid(d + 1, &gid) < 0)
return -ESRCH;
mn = strndup(e, d - e);
if (!mn)
return -ENOMEM;
machine = hashmap_get(m->machines, mn);
if (!mn)
return -ESRCH;
if (machine->class != MACHINE_CONTAINER)
return -ESRCH;
r = machine_translate_gid(machine, gid, &converted_gid);
if (r < 0)
return r;
*ret_gid = converted_gid;
return 0;
}
static int vl_method_get_group_record(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
{ "gid", JSON_VARIANT_UNSIGNED, json_dispatch_uid_gid, offsetof(LookupParameters, gid), 0 },
{ "groupName", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, group_name), JSON_SAFE },
{ "service", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
{}
};
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
LookupParameters p = {
.gid = GID_INVALID,
};
_cleanup_free_ char *found_name = NULL;
uid_t found_gid = GID_INVALID, gid;
Manager *m = userdata;
const char *gn;
int r;
assert(parameters);
assert(m);
r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
if (r < 0)
return r;
if (!streq_ptr(p.service, "io.systemd.Machine"))
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
if (gid_is_valid(p.gid))
r = group_lookup_gid(m, p.gid, &found_name);
else if (p.group_name)
r = group_lookup_name(m, p.group_name, (uid_t*) &found_gid);
else
return varlink_error(link, "io.systemd.UserDatabase.EnumerationNotSupported", NULL);
if (r == -ESRCH)
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
if (r < 0)
return r;
gid = gid_is_valid(found_gid) ? found_gid : p.gid;
gn = found_name ?: p.group_name;
if (!group_match_lookup_parameters(&p, gn, gid))
return varlink_error(link, "io.systemd.UserDatabase.ConflictingRecordFound", NULL);
r = build_group_json(gn, gid, &v);
if (r < 0)
return r;
return varlink_reply(link, v);
}
static int vl_method_get_memberships(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata) {
static const JsonDispatch dispatch_table[] = {
{ "userName", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, user_name), JSON_SAFE },
{ "groupName", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, group_name), JSON_SAFE },
{ "service", JSON_VARIANT_STRING, json_dispatch_const_string, offsetof(LookupParameters, service), 0 },
{}
};
LookupParameters p = {};
int r;
assert(parameters);
r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
if (r < 0)
return r;
if (!streq_ptr(p.service, "io.systemd.Machine"))
return varlink_error(link, "io.systemd.UserDatabase.BadService", NULL);
/* We don't support auxiliary groups for machines. */
return varlink_error(link, "io.systemd.UserDatabase.NoRecordFound", NULL);
}
int manager_varlink_init(Manager *m) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
assert(m);
if (m->varlink_server)
return 0;
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID);
if (r < 0)
return log_error_errno(r, "Failed to allocate varlink server object: %m");
varlink_server_set_userdata(s, m);
r = varlink_server_bind_method_many(
s,
"io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,
"io.systemd.UserDatabase.GetGroupRecord", vl_method_get_group_record,
"io.systemd.UserDatabase.GetMemberships", vl_method_get_memberships);
if (r < 0)
return log_error_errno(r, "Failed to register varlink methods: %m");
(void) mkdir_p("/run/systemd/userdb", 0755);
r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.Machine", 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket: %m");
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
if (r < 0)
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
m->varlink_server = TAKE_PTR(s);
return 0;
}
void manager_varlink_done(Manager *m) {
assert(m);
m->varlink_server = varlink_server_unref(m->varlink_server);
}

View File

@ -1,7 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "machined.h"
int manager_varlink_init(Manager *m);
void manager_varlink_done(Manager *m);

View File

@ -20,7 +20,6 @@
#include "hostname-util.h" #include "hostname-util.h"
#include "label.h" #include "label.h"
#include "machine-image.h" #include "machine-image.h"
#include "machined-varlink.h"
#include "machined.h" #include "machined.h"
#include "main-func.h" #include "main-func.h"
#include "process-util.h" #include "process-util.h"
@ -87,8 +86,6 @@ static Manager* manager_unref(Manager *m) {
bus_verify_polkit_async_registry_free(m->polkit_registry); bus_verify_polkit_async_registry_free(m->polkit_registry);
manager_varlink_done(m);
sd_bus_flush_close_unref(m->bus); sd_bus_flush_close_unref(m->bus);
sd_event_unref(m->event); sd_event_unref(m->event);
@ -275,11 +272,6 @@ static int manager_startup(Manager *m) {
if (r < 0) if (r < 0)
return r; return r;
/* Set up Varlink service */
r = manager_varlink_init(m);
if (r < 0)
return r;
/* Deserialize state */ /* Deserialize state */
manager_enumerate_machines(m); manager_enumerate_machines(m);
@ -299,9 +291,6 @@ static bool check_idle(void *userdata) {
if (m->operations) if (m->operations)
return false; return false;
if (varlink_server_current_connections(m->varlink_server) > 0)
return false;
manager_gc(m, true); manager_gc(m, true);
return hashmap_isempty(m->machines); return hashmap_isempty(m->machines);

View File

@ -6,15 +6,15 @@
#include "sd-bus.h" #include "sd-bus.h"
#include "sd-event.h" #include "sd-event.h"
#include "hashmap.h"
#include "list.h"
typedef struct Manager Manager; typedef struct Manager Manager;
#include "hashmap.h"
#include "image-dbus.h" #include "image-dbus.h"
#include "list.h"
#include "machine-dbus.h" #include "machine-dbus.h"
#include "machine.h" #include "machine.h"
#include "operation.h" #include "operation.h"
#include "varlink.h"
struct Manager { struct Manager {
sd_event *event; sd_event *event;
@ -37,8 +37,6 @@ struct Manager {
unsigned n_operations; unsigned n_operations;
sd_event_source *nscd_cache_flush_event; sd_event_source *nscd_cache_flush_event;
VarlinkServer *varlink_server;
}; };
int manager_add_machine(Manager *m, const char *name, Machine **_machine); int manager_add_machine(Manager *m, const char *name, Machine **_machine);
@ -58,6 +56,3 @@ int manager_unit_is_active(Manager *manager, const char *unit);
int manager_job_is_active(Manager *manager, const char *path); int manager_job_is_active(Manager *manager, const char *path);
int manager_enqueue_nscd_cache_flush(Manager *m); int manager_enqueue_nscd_cache_flush(Manager *m);
int manager_find_machine_for_uid(Manager *m, uid_t host_uid, Machine **ret_machine, uid_t *ret_internal_uid);
int manager_find_machine_for_gid(Manager *m, gid_t host_gid, Machine **ret_machine, gid_t *ret_internal_gid);

View File

@ -6,16 +6,14 @@ systemd_machined_sources = files('''
'''.split()) '''.split())
libmachine_core_sources = files(''' libmachine_core_sources = files('''
image-dbus.c
image-dbus.h
machine-dbus.c
machine-dbus.h
machine.c machine.c
machine.h machine.h
machined-core.c
machined-dbus.c machined-dbus.c
machined-varlink.c machined-core.c
machined-varlink.h machine-dbus.c
machine-dbus.h
image-dbus.c
image-dbus.h
operation.c operation.c
operation.h operation.h
'''.split()) '''.split())

View File

@ -288,7 +288,7 @@ int link_set_bond(Link *link) {
r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler, r = netlink_call_async(link->manager->rtnl, NULL, req, link_set_bond_handler,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);

View File

@ -218,7 +218,7 @@ int link_set_bridge(Link *link) {
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m"); 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) { 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); r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, link->network->allow_port_to_be_root);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m"); return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");

View File

@ -1662,7 +1662,7 @@ static int link_status_one(
r = table_add_many(table, r = table_add_many(table,
TABLE_EMPTY, TABLE_EMPTY,
TABLE_STRING, "Mode:", TABLE_STRING, "Mode:",
TABLE_STRING, bond_mode_to_string(info->mode), TABLE_STRING, bond_mode_to_string(info->mode),
TABLE_EMPTY, TABLE_EMPTY,
TABLE_STRING, "Miimon:", TABLE_STRING, "Miimon:",
TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->miimon), TABLE_TIMESPAN_MSEC, jiffies_to_usec(info->miimon),

View File

@ -444,8 +444,6 @@ static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL) if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, "Could not drop address"); log_link_message_warning_errno(link, m, r, "Could not drop address");
else
(void) manager_rtnl_process_address(rtnl, m, link->manager);
return 1; return 1;
} }

View File

@ -20,12 +20,12 @@
#include "sysctl-util.h" #include "sysctl-util.h"
#include "web-util.h" #include "web-util.h"
static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback); static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback); static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all, link_netlink_message_handler_t callback); static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all);
static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, link_netlink_message_handler_t callback); static int dhcp_remove_address(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, link_netlink_message_handler_t callback);
static int dhcp4_update_address(Link *link, bool announce); static int dhcp_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link);
static int dhcp4_remove_all(Link *link); static int dhcp_lease_renew(sd_dhcp_client *client, Link *link);
void dhcp4_release_old_lease(Link *link) { void dhcp4_release_old_lease(Link *link) {
struct in_addr address = {}, address_old = {}; struct in_addr address = {}, address_old = {};
@ -40,9 +40,9 @@ void dhcp4_release_old_lease(Link *link) {
(void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old); (void) sd_dhcp_lease_get_address(link->dhcp_lease_old, &address_old);
(void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
(void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false, NULL); (void) dhcp_remove_routes(link, link->dhcp_lease_old, &address_old, false);
(void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false, NULL); (void) dhcp_remove_router(link, link->dhcp_lease_old, &address_old, false);
(void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false, NULL); (void) dhcp_remove_dns_routes(link, link->dhcp_lease_old, &address_old, false);
if (!in4_addr_equal(&address_old, &address)) if (!in4_addr_equal(&address_old, &address))
(void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old, NULL); (void) dhcp_remove_address(link, link->dhcp_lease_old, &address_old, NULL);
@ -88,12 +88,17 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
if (link->dhcp4_messages == 0) { if (link->dhcp4_messages == 0) {
if (link->dhcp4_route_failed) { if (link->dhcp4_route_failed) {
struct in_addr address = {};
link->dhcp4_route_failed = false; link->dhcp4_route_failed = false;
link->dhcp4_route_retrying = true; link->dhcp4_route_retrying = true;
r = dhcp4_remove_all(link); (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0) (void) dhcp_remove_routes(link, link->dhcp_lease, &address, true);
link_enter_failed(link); (void) dhcp_remove_router(link, link->dhcp_lease, &address, true);
(void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true);
(void) dhcp_remove_address(link, link->dhcp_lease, &address, dhcp_remove_address_handler);
return 1; return 1;
} }
if (!link->network->dhcp_send_decline) if (!link->network->dhcp_send_decline)
@ -172,7 +177,7 @@ static int link_set_dns_routes(Link *link, const struct in_addr *address) {
r = route_new(&route); r = route_new(&route);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m"); return log_link_error_errno(link, r, "Could not allocate route: %m");
/* Set routes to DNS servers. */ /* Set routes to DNS servers. */
@ -261,7 +266,7 @@ static int link_set_dhcp_routes(Link *link) {
r = dhcp_prefix_route_from_lease(link->dhcp_lease, table, &address, &prefix_route); r = dhcp_prefix_route_from_lease(link->dhcp_lease, table, &address, &prefix_route);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not create prefix route: %m"); return log_link_error_errno(link, r, "Could not create prefix route: %m");
r = dhcp_route_configure(&prefix_route, link); r = dhcp_route_configure(&prefix_route, link);
if (r < 0) if (r < 0)
@ -339,7 +344,7 @@ static int link_set_dhcp_routes(Link *link) {
r = route_new(&route_gw); r = route_new(&route_gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m"); return log_link_error_errno(link, r, "Could not allocate route: %m");
/* The dhcp netmask may mask out the gateway. Add an explicit /* The dhcp netmask may mask out the gateway. Add an explicit
* route for the gw host so that we can route no matter the * route for the gw host so that we can route no matter the
@ -396,26 +401,7 @@ static int link_set_dhcp_routes(Link *link) {
return link_set_dns_routes(link, &address); return link_set_dns_routes(link, &address);
} }
static int dhcp_route_remove(Route *route, Link *link, link_netlink_message_handler_t callback) { static int dhcp_remove_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
int r;
r = route_remove(route, link, callback);
if (r < 0)
return r;
if (callback)
link->dhcp4_remove_messages++;
return 0;
}
static int dhcp_remove_routes(
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
_cleanup_free_ sd_dhcp_route **routes = NULL; _cleanup_free_ sd_dhcp_route **routes = NULL;
uint32_t table; uint32_t table;
int n, i, r; int n, i, r;
@ -454,21 +440,13 @@ static int dhcp_remove_routes(
if (!remove_all && set_contains(link->dhcp_routes, route)) if (!remove_all && set_contains(link->dhcp_routes, route))
continue; continue;
r = dhcp_route_remove(route, link, callback); (void) route_remove(route, link, NULL);
if (r < 0)
return r;
} }
return n; return n;
} }
static int dhcp_remove_router( static int dhcp_remove_router(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
_cleanup_(route_freep) Route *route_gw = NULL, *route = NULL; _cleanup_(route_freep) Route *route_gw = NULL, *route = NULL;
const struct in_addr *router; const struct in_addr *router;
uint32_t table; uint32_t table;
@ -506,11 +484,8 @@ static int dhcp_remove_router(
route_gw->priority = link->network->dhcp_route_metric; route_gw->priority = link->network->dhcp_route_metric;
route_gw->table = table; route_gw->table = table;
if (remove_all || !set_contains(link->dhcp_routes, route_gw)) { if (remove_all || !set_contains(link->dhcp_routes, route_gw))
r = dhcp_route_remove(route_gw, link, callback); (void) route_remove(route_gw, link, NULL);
if (r < 0)
return r;
}
r = route_new(&route); r = route_new(&route);
if (r < 0) if (r < 0)
@ -523,11 +498,8 @@ static int dhcp_remove_router(
route->priority = link->network->dhcp_route_metric; route->priority = link->network->dhcp_route_metric;
route->table = table; route->table = table;
if (remove_all || !set_contains(link->dhcp_routes, route)) { if (remove_all || !set_contains(link->dhcp_routes, route))
r = dhcp_route_remove(route, link, callback); (void) route_remove(route, link, NULL);
if (r < 0)
return r;
}
Route *rt; Route *rt;
LIST_FOREACH(routes, rt, link->network->static_routes) { LIST_FOREACH(routes, rt, link->network->static_routes) {
@ -540,21 +512,13 @@ static int dhcp_remove_router(
if (!remove_all && in4_addr_equal(router, &rt->gw.in)) if (!remove_all && in4_addr_equal(router, &rt->gw.in))
continue; continue;
r = dhcp_route_remove(rt, link, callback); (void) route_remove(rt, link, NULL);
if (r < 0)
return r;
} }
return 0; return 0;
} }
static int dhcp_remove_dns_routes( static int dhcp_remove_dns_routes(Link *link, sd_dhcp_lease *lease, const struct in_addr *address, bool remove_all) {
Link *link,
sd_dhcp_lease *lease,
const struct in_addr *address,
bool remove_all,
link_netlink_message_handler_t callback) {
const struct in_addr *dns; const struct in_addr *dns;
uint32_t table; uint32_t table;
int i, n, r; int i, n, r;
@ -580,7 +544,7 @@ static int dhcp_remove_dns_routes(
r = route_new(&route); r = route_new(&route);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m"); return log_link_error_errno(link, r, "Could not allocate route: %m");
route->family = AF_INET; route->family = AF_INET;
route->dst.in = dns[i]; route->dst.in = dns[i];
@ -594,9 +558,7 @@ static int dhcp_remove_dns_routes(
if (!remove_all && set_contains(link->dhcp_routes, route)) if (!remove_all && set_contains(link->dhcp_routes, route))
continue; continue;
r = dhcp_route_remove(route, link, callback); (void) route_remove(route, link, NULL);
if (r < 0)
return r;
} }
if (!link_prefixroute(link)) { if (!link_prefixroute(link)) {
@ -604,18 +566,36 @@ static int dhcp_remove_dns_routes(
r = dhcp_prefix_route_from_lease(lease, table, address, &prefix_route); r = dhcp_prefix_route_from_lease(lease, table, address, &prefix_route);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not create prefix route: %m"); return log_link_warning_errno(link, r, "Could not delete prefix route: %m");
if (remove_all || !set_contains(link->dhcp_routes, prefix_route)) { if (remove_all || !set_contains(link->dhcp_routes, prefix_route))
r = dhcp_route_remove(prefix_route, link, callback); (void) route_remove(prefix_route, link, NULL);
if (r < 0)
return r;
}
} }
return 0; return 0;
} }
static int dhcp_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
/* This is only used when retrying to assign the address received from DHCPv4 server.
* See dhcp4_route_handler(). */
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_message_warning_errno(link, m, r, "Failed to remove DHCPv4 address, ignoring");
else
(void) manager_rtnl_process_address(rtnl, m, link->manager);
(void) dhcp_lease_renew(link->dhcp_client, link);
return 1;
}
static int dhcp_remove_address( static int dhcp_remove_address(
Link *link, sd_dhcp_lease *lease, Link *link, sd_dhcp_lease *lease,
const struct in_addr *address, const struct in_addr *address,
@ -641,12 +621,7 @@ static int dhcp_remove_address(
if (sd_dhcp_lease_get_netmask(lease, &netmask) >= 0) if (sd_dhcp_lease_get_netmask(lease, &netmask) >= 0)
a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask); a->prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
r = address_remove(a, link, callback); (void) address_remove(a, link, callback);
if (r < 0)
return r;
if (callback)
link->dhcp4_remove_messages++;
return 0; return 0;
} }
@ -701,90 +676,8 @@ static int dhcp_reset_hostname(Link *link) {
return 0; return 0;
} }
static int dhcp4_remove_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->dhcp4_remove_messages > 0);
link->dhcp4_remove_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH)
log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 route, ignoring");
if (link->dhcp4_remove_messages == 0) {
r = dhcp4_update_address(link, false);
if (r < 0)
link_enter_failed(link);
}
return 1;
}
static int dhcp4_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->dhcp4_remove_messages > 0);
link->dhcp4_remove_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 address, ignoring");
else
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp4_remove_messages == 0) {
r = dhcp4_update_address(link, false);
if (r < 0)
link_enter_failed(link);
}
return 1;
}
static int dhcp4_remove_all(Link *link) {
struct in_addr address;
int r;
assert(link);
assert(link->dhcp_lease);
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to get DHCPv4 address: %m");
r = dhcp_remove_routes(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r;
r = dhcp_remove_router(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r;
r = dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true, dhcp4_remove_route_handler);
if (r < 0)
return r;
r = dhcp_remove_address(link, link->dhcp_lease, &address, dhcp4_remove_address_handler);
if (r < 0)
return r;
return 0;
}
static int dhcp_lease_lost(Link *link) { static int dhcp_lease_lost(Link *link) {
int r; struct in_addr address = {};
assert(link); assert(link);
assert(link->dhcp_lease); assert(link->dhcp_lease);
@ -793,17 +686,13 @@ static int dhcp_lease_lost(Link *link) {
link->dhcp4_configured = false; link->dhcp4_configured = false;
r = dhcp4_remove_all(link); (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0) (void) dhcp_remove_routes(link, link->dhcp_lease, &address, true);
return r; (void) dhcp_remove_router(link, link->dhcp_lease, &address, true);
(void) dhcp_remove_dns_routes(link, link->dhcp_lease, &address, true);
r = dhcp_reset_mtu(link); (void) dhcp_remove_address(link, link->dhcp_lease, &address, NULL);
if (r < 0) (void) dhcp_reset_mtu(link);
return r; (void) dhcp_reset_hostname(link);
r = dhcp_reset_hostname(link);
if (r < 0)
return r;
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link_dirty(link); link_dirty(link);
@ -941,81 +830,30 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1; return 1;
} }
static int dhcp4_update_address(Link *link, bool announce) { static int dhcp4_update_address(Link *link,
struct in_addr *address,
struct in_addr *netmask,
uint32_t lifetime) {
_cleanup_(address_freep) Address *addr = NULL; _cleanup_(address_freep) Address *addr = NULL;
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
struct in_addr address, netmask;
unsigned prefixlen; unsigned prefixlen;
int r; int r;
assert(link); assert(address);
assert(link->network); assert(netmask);
assert(lifetime);
if (!link->dhcp_lease) prefixlen = in4_addr_netmask_to_prefixlen(netmask);
return 0;
link_set_state(link, LINK_STATE_CONFIGURING);
link->dhcp4_configured = false;
/* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they
* are called, the related flags must be cleared. Otherwise, the link becomes configured state
* before routes are configured. */
link->static_routes_configured = false;
link->static_nexthops_configured = false;
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no address: %m");
r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
}
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
if (announce) {
const struct in_addr *router;
r = sd_dhcp_lease_get_router(link->dhcp_lease, &router);
if (r < 0 && r != -ENODATA)
return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
if (r > 0 && !in4_addr_is_null(&router[0]))
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
ADDRESS_FMT_VAL(address),
prefixlen,
ADDRESS_FMT_VAL(router[0])),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen,
"GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0]));
else
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
ADDRESS_FMT_VAL(address),
prefixlen),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen);
}
r = address_new(&addr); r = address_new(&addr);
if (r < 0) if (r < 0)
return log_oom(); return r;
addr->family = AF_INET; addr->family = AF_INET;
addr->in_addr.in.s_addr = address.s_addr; addr->in_addr.in.s_addr = address->s_addr;
addr->cinfo.ifa_prefered = lifetime; addr->cinfo.ifa_prefered = lifetime;
addr->cinfo.ifa_valid = lifetime; addr->cinfo.ifa_valid = lifetime;
addr->prefixlen = prefixlen; addr->prefixlen = prefixlen;
addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr; addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr;
addr->prefix_route = link_prefixroute(link); addr->prefix_route = link_prefixroute(link);
/* allow reusing an existing address and simply update its lifetime /* allow reusing an existing address and simply update its lifetime
@ -1029,34 +867,102 @@ static int dhcp4_update_address(Link *link, bool announce) {
static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) { static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
sd_dhcp_lease *lease; sd_dhcp_lease *lease;
struct in_addr address;
struct in_addr netmask;
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
int r; int r;
assert(link); assert(link);
assert(client); assert(client);
assert(link->network);
r = sd_dhcp_client_get_lease(client, &lease); r = sd_dhcp_client_get_lease(client, &lease);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no lease: %m"); return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
sd_dhcp_lease_unref(link->dhcp_lease); sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp4_configured = false;
link->dhcp_lease = sd_dhcp_lease_ref(lease); link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link); link_dirty(link);
return dhcp4_update_address(link, false); r = sd_dhcp_lease_get_address(lease, &address);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no address: %m");
r = sd_dhcp_lease_get_netmask(lease, &netmask);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
}
r = dhcp4_update_address(link, &address, &netmask, lifetime);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update IP address: %m");
return 0;
} }
static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
const struct in_addr *router;
sd_dhcp_lease *lease; sd_dhcp_lease *lease;
struct in_addr address;
struct in_addr netmask;
unsigned prefixlen;
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
int r; int r;
assert(client); assert(client);
assert(link); assert(link);
link->dhcp4_configured = false;
r = sd_dhcp_client_get_lease(client, &lease); r = sd_dhcp_client_get_lease(client, &lease);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: No lease: %m"); return log_link_error_errno(link, r, "DHCP error: No lease: %m");
sd_dhcp_lease_unref(link->dhcp_lease); r = sd_dhcp_lease_get_address(lease, &address);
if (r < 0)
return log_link_error_errno(link, r, "DHCP error: No address: %m");
r = sd_dhcp_lease_get_netmask(lease, &netmask);
if (r < 0)
return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
r = sd_dhcp_lease_get_lifetime(lease, &lifetime);
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m");
}
r = sd_dhcp_lease_get_router(lease, &router);
if (r < 0 && r != -ENODATA)
return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m");
if (r > 0 && !in4_addr_is_null(&router[0]))
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u",
ADDRESS_FMT_VAL(address),
prefixlen,
ADDRESS_FMT_VAL(router[0])),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen,
"GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(router[0]));
else
log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u",
ADDRESS_FMT_VAL(address),
prefixlen),
"ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen);
link->dhcp_lease = sd_dhcp_lease_ref(lease); link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link); link_dirty(link);
@ -1107,14 +1013,9 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
} }
} }
if (link->dhcp4_remove_messages == 0) { r = dhcp4_update_address(link, &address, &netmask, lifetime);
r = dhcp4_update_address(link, true); if (r < 0)
if (r < 0) return log_link_warning_errno(link, r, "Could not update IP address: %m");
return r;
} else
log_link_debug(link,
"The link has previously assigned DHCPv4 address or routes. "
"The newly assigned address and routes will set up after old ones are removed.");
return 0; return 0;
} }

View File

@ -24,6 +24,7 @@
#include "radv-internal.h" #include "radv-internal.h"
#include "web-util.h" #include "web-util.h"
static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link);
static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr); static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr);
static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link); static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link);
static int dhcp6_prefix_remove_all(Manager *m, Link *link); static int dhcp6_prefix_remove_all(Manager *m, Link *link);
@ -32,7 +33,7 @@ static int dhcp6_assign_delegated_prefix(Link *link, const struct in6_addr *pref
uint32_t lifetime_preferred, uint32_t lifetime_preferred,
uint32_t lifetime_valid); uint32_t lifetime_valid);
bool dhcp6_get_prefix_delegation(Link *link) { static bool dhcp6_get_prefix_delegation(Link *link) {
if (!link->network) if (!link->network)
return false; return false;
@ -124,7 +125,7 @@ static int dhcp6_get_preferred_delegated_prefix(
r = in_addr_prefix_next(AF_INET6, &prefix, 64); r = in_addr_prefix_next(AF_INET6, &prefix, 64);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Can't allocate another prefix. Out of address space?: %m"); return log_link_error_errno(link, r, "Can't allocate another prefix. Out of address space?");
} }
return log_link_warning_errno(link, SYNTHETIC_ERRNO(ERANGE), "Couldn't find a suitable prefix. Ran out of address space."); return log_link_warning_errno(link, SYNTHETIC_ERRNO(ERANGE), "Couldn't find a suitable prefix. Ran out of address space.");
@ -171,9 +172,11 @@ static int dhcp6_pd_prefix_assign(Link *link, struct in6_addr *prefix,
if (r < 0) if (r < 0)
return r; return r;
r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid); if (link->network->dhcp6_pd_assign_prefix) {
if (r < 0) r = dhcp6_assign_delegated_prefix(link, prefix, prefix_len, lifetime_preferred, lifetime_valid);
return r; if (r < 0)
return r;
}
return 0; return 0;
} }
@ -321,25 +324,13 @@ static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link
int r; int r;
assert(link); assert(link);
assert(link->dhcp6_route_messages > 0);
link->dhcp6_route_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST)
log_link_message_warning_errno(link, m, r, "Failed to add unreachable route for DHCPv6 delegated subnet"); log_link_message_warning_errno(link, m, r, "Received error when adding unreachable route for DHCPv6 delegated subnet");
link_enter_failed(link);
return 1;
}
if (link->dhcp6_route_messages == 0) {
log_link_debug(link, "Unreachable routes for DHCPv6 delegated subnets set");
link->dhcp6_route_configured = true;
link_check_ready(link);
}
return 1; return 1;
} }
@ -351,8 +342,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
uint8_t pd_prefix_len; uint8_t pd_prefix_len;
int r; int r;
link->dhcp6_route_configured = false;
r = sd_dhcp6_client_get_lease(client, &lease); r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0) if (r < 0)
return r; return r;
@ -397,8 +386,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
pd_prefix_len); pd_prefix_len);
continue; continue;
} }
if (r > 0)
link->dhcp6_route_messages++;
log_link_debug(link, "Configuring unreachable route for %s/%u", log_link_debug(link, "Configuring unreachable route for %s/%u",
strnull(buf), pd_prefix_len); strnull(buf), pd_prefix_len);
@ -448,14 +435,6 @@ static int dhcp6_lease_pd_prefix_acquired(sd_dhcp6_client *client, Link *link) {
* fulfill those with the next available pd delegated prefix. */ * fulfill those with the next available pd delegated prefix. */
} }
if (link->dhcp6_route_messages == 0) {
link->dhcp6_route_configured = true;
link_check_ready(link);
} else {
log_link_debug(link, "Setting unreachable routes for DHCPv6 delegated subnets");
link_set_state(link, LINK_STATE_CONFIGURING);
}
return 0; return 0;
} }
@ -482,14 +461,14 @@ int dhcp6_request_prefix_delegation(Link *link) {
r = sd_dhcp6_client_get_prefix_delegation(l->dhcp6_client, &enabled); r = sd_dhcp6_client_get_prefix_delegation(l->dhcp6_client, &enabled);
if (r < 0) { if (r < 0) {
log_link_warning_errno(l, r, "Cannot get prefix delegation when adding new link: %m"); log_link_warning_errno(l, r, "Cannot get prefix delegation when adding new link");
continue; continue;
} }
if (enabled == 0) { if (enabled == 0) {
r = sd_dhcp6_client_set_prefix_delegation(l->dhcp6_client, 1); r = sd_dhcp6_client_set_prefix_delegation(l->dhcp6_client, 1);
if (r < 0) { if (r < 0) {
log_link_warning_errno(l, r, "Cannot enable prefix delegation when adding new link: 5m"); log_link_warning_errno(l, r, "Cannot enable prefix delegation when adding new link");
continue; continue;
} }
} }
@ -507,13 +486,13 @@ int dhcp6_request_prefix_delegation(Link *link) {
r = sd_dhcp6_client_stop(l->dhcp6_client); r = sd_dhcp6_client_stop(l->dhcp6_client);
if (r < 0) { if (r < 0) {
log_link_warning_errno(l, r, "Cannot stop DHCPv6 prefix delegation client after adding new link: %m"); log_link_warning_errno(l, r, "Cannot stop DHCPv6 prefix delegation client after adding new link");
continue; continue;
} }
r = sd_dhcp6_client_start(l->dhcp6_client); r = sd_dhcp6_client_start(l->dhcp6_client);
if (r < 0) { if (r < 0) {
log_link_warning_errno(l, r, "Cannot restart DHCPv6 prefix delegation client after adding new link: %m"); log_link_warning_errno(l, r, "Cannot restart DHCPv6 prefix delegation client after adding new link");
continue; continue;
} }
@ -527,9 +506,6 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
int r; int r;
assert(link); assert(link);
assert(link->dhcp6_address_messages > 0);
link->dhcp6_address_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
@ -542,14 +518,10 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
} else if (r >= 0) } else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager); (void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp6_address_messages == 0) { r = link_request_set_routes(link);
log_link_debug(link, "DHCPv6 addresses set"); if (r < 0) {
link->dhcp6_address_configured = true; link_enter_failed(link);
r = link_request_set_routes(link); return 1;
if (r < 0) {
link_enter_failed(link);
return 1;
}
} }
return 1; return 1;
@ -584,8 +556,6 @@ static int dhcp6_address_change(
r = address_configure(addr, link, dhcp6_address_handler, true); r = address_configure(addr, link, dhcp6_address_handler, true);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); return log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m");
if (r > 0)
link->dhcp6_address_messages++;
return 0; return 0;
} }
@ -596,13 +566,12 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
struct in6_addr ip6_addr; struct in6_addr ip6_addr;
uint32_t lifetime_preferred, lifetime_valid; uint32_t lifetime_preferred, lifetime_valid;
link->dhcp6_address_configured = false;
r = sd_dhcp6_client_get_lease(client, &lease); r = sd_dhcp6_client_get_lease(client, &lease);
if (r < 0) if (r < 0)
return r; return r;
sd_dhcp6_lease_reset_address_iter(lease); sd_dhcp6_lease_reset_address_iter(lease);
while (sd_dhcp6_lease_get_address(lease, &ip6_addr, while (sd_dhcp6_lease_get_address(lease, &ip6_addr,
&lifetime_preferred, &lifetime_preferred,
&lifetime_valid) >= 0) { &lifetime_valid) >= 0) {
@ -612,19 +581,6 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
return r; return r;
} }
if (link->dhcp6_address_messages == 0) {
link->dhcp6_address_configured = true;
return link_request_set_routes(link);
} else {
log_link_debug(link, "Setting DHCPv6 addresses");
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
* Before they are called, the related flags must be cleared. Otherwise, the link
* becomes configured state before routes are configured. */
link->static_routes_configured = false;
link->static_nexthops_configured = false;
link_set_state(link, LINK_STATE_CONFIGURING);
}
return 0; return 0;
} }
@ -649,6 +605,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
(void) dhcp6_prefix_remove_all(link->manager, link); (void) dhcp6_prefix_remove_all(link->manager, link);
link_dirty(link); link_dirty(link);
link->dhcp6_configured = false;
break; break;
case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
@ -660,7 +617,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
r = dhcp6_lease_pd_prefix_acquired(client, link); r = dhcp6_lease_pd_prefix_acquired(client, link);
if (r < 0) if (r < 0)
log_link_debug_errno(link, r, "DHCPv6 did not receive prefixes to delegate: %m"); log_link_debug(link, "DHCPv6 did not receive prefixes to delegate");
_fallthrough_; _fallthrough_;
case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
@ -671,6 +628,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
} }
link_dirty(link); link_dirty(link);
link->dhcp6_configured = true;
break; break;
default: default:
@ -707,7 +665,7 @@ int dhcp6_request_address(Link *link, int ir) {
r = sd_dhcp6_client_set_address_request(link->dhcp6_client, r = sd_dhcp6_client_set_address_request(link->dhcp6_client,
false); false);
if (r < 0) if (r < 0 )
return r; return r;
ir = false; ir = false;
@ -854,6 +812,7 @@ int dhcp6_configure(Link *link) {
log_link_debug(link, "DHCP6 CLIENT: Failed to set request flag for '%u' already exists, ignoring.", option); log_link_debug(link, "DHCP6 CLIENT: Failed to set request flag for '%u' already exists, ignoring.", option);
continue; continue;
} }
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for '%u': %m", option); return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set request flag for '%u': %m", option);
} }
@ -906,30 +865,21 @@ static Link *dhcp6_prefix_get(Manager *m, struct in6_addr *addr) {
return hashmap_get(m->dhcp6_prefixes, addr); return hashmap_get(m->dhcp6_prefixes, addr);
} }
static int dhcp6_pd_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) { static int dhcp6_route_add_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
assert(link->dhcp6_pd_route_messages > 0);
link->dhcp6_pd_route_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Failed to add DHCPv6 Prefix Delegation route"); log_link_message_warning_errno(link, m, r, "Received error adding DHCPv6 Prefix Delegation route");
link_enter_failed(link); link_enter_failed(link);
return 1; return 1;
} }
if (link->dhcp6_pd_route_messages == 0) {
log_link_debug(link, "DHCPv6 prefix delegation routes set");
link->dhcp6_pd_route_configured = true;
link_check_ready(link);
}
return 1; return 1;
} }
@ -951,14 +901,9 @@ static int dhcp6_prefix_add(Manager *m, struct in6_addr *addr, Link *link) {
route->dst.in6 = *addr; route->dst.in6 = *addr;
route->dst_prefixlen = 64; route->dst_prefixlen = 64;
link->dhcp6_pd_route_configured = false; r = route_configure(route, link, dhcp6_route_add_handler);
link_set_state(link, LINK_STATE_CONFIGURING);
r = route_configure(route, link, dhcp6_pd_route_handler);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0)
link->dhcp6_pd_route_messages++;
(void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf); (void) in_addr_to_string(AF_INET6, (union in_addr_union *) addr, &buf);
log_link_debug(link, "Adding prefix route %s/64", strnull(buf)); log_link_debug(link, "Adding prefix route %s/64", strnull(buf));
@ -1053,33 +998,26 @@ static int dhcp6_prefix_remove_all(Manager *m, Link *link) {
return 0; return 0;
} }
static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp6_assign_delegeted_prefix_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
assert(link->dhcp6_pd_address_messages > 0);
link->dhcp6_pd_address_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 delegated prefix address"); log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 delegated prefix address ");
link_enter_failed(link); link_enter_failed(link);
return 1; return 1;
} else if (r >= 0) } else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager); (void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp6_pd_address_messages == 0) { r = link_request_set_routes(link);
log_link_debug(link, "DHCPv6 delegated prefix addresses set"); if (r < 0) {
link->dhcp6_pd_address_configured = true; link_enter_failed(link);
r = link_request_set_routes(link); return 1;
if (r < 0) {
link_enter_failed(link);
return 1;
}
} }
return 1; return 1;
@ -1098,10 +1036,8 @@ static int dhcp6_assign_delegated_prefix(Link *link,
assert(link->network); assert(link->network);
assert(prefix); assert(prefix);
if (!link->network->dhcp6_pd_assign_prefix) { if (!link->network->dhcp6_pd_assign_prefix)
link->dhcp6_pd_address_configured = true;
return 0; return 0;
}
r = address_new(&address); r = address_new(&address);
if (r < 0) if (r < 0)
@ -1122,19 +1058,11 @@ static int dhcp6_assign_delegated_prefix(Link *link,
address->cinfo.ifa_prefered = lifetime_preferred; address->cinfo.ifa_prefered = lifetime_preferred;
address->cinfo.ifa_valid = lifetime_valid; address->cinfo.ifa_valid = lifetime_valid;
/* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they
* are called, the related flags must be cleared. Otherwise, the link becomes configured state
* before routes are configured. */
link->static_routes_configured = false;
link->static_nexthops_configured = false;
link->dhcp6_pd_address_configured = false;
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
r = address_configure(address, link, dhcp6_pd_address_handler, true); r = address_configure(address, link, dhcp6_assign_delegeted_prefix_address_handler, true);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to set acquired DHCPv6 delegated prefix address: %m"); return log_link_warning_errno(link, r, "Failed to set acquired DHCPv6 delegated prefix address: %m");
if (r > 0)
link->dhcp6_pd_address_messages++;
return 0; return 0;
} }

View File

@ -17,7 +17,6 @@ typedef enum DHCP6ClientStartMode {
typedef struct Link Link; typedef struct Link Link;
typedef struct Manager Manager; typedef struct Manager Manager;
bool dhcp6_get_prefix_delegation(Link *link);
int dhcp6_request_prefix_delegation(Link *link); int dhcp6_request_prefix_delegation(Link *link);
int dhcp6_configure(Link *link); int dhcp6_configure(Link *link);
int dhcp6_request_address(Link *link, int ir); int dhcp6_request_address(Link *link, int ir);

View File

@ -932,9 +932,10 @@ static int link_request_set_routing_policy_rule(Link *link) {
} }
routing_policy_rule_purge(link->manager, link); routing_policy_rule_purge(link->manager, link);
if (link->routing_policy_rule_messages == 0) if (link->routing_policy_rule_messages == 0) {
link->routing_policy_rules_configured = true; link->routing_policy_rules_configured = true;
else { link_check_ready(link);
} else {
log_link_debug(link, "Setting routing policy rules"); log_link_debug(link, "Setting routing policy rules");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
} }
@ -971,12 +972,10 @@ static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link)
return 1; return 1;
} }
static int link_request_set_nexthop(Link *link) { int link_request_set_nexthop(Link *link) {
NextHop *nh; NextHop *nh;
int r; int r;
link->static_nexthops_configured = false;
LIST_FOREACH(nexthops, nh, link->network->static_nexthops) { LIST_FOREACH(nexthops, nh, link->network->static_nexthops) {
r = nexthop_configure(nh, link, nexthop_handler); r = nexthop_configure(nh, link, nexthop_handler);
if (r < 0) if (r < 0)
@ -1019,7 +1018,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
if (link->route_messages == 0) { if (link->route_messages == 0) {
log_link_debug(link, "Routes set"); log_link_debug(link, "Routes set");
link->static_routes_configured = true; link->static_routes_configured = true;
link_request_set_nexthop(link); link_check_ready(link);
} }
return 1; return 1;
@ -1041,6 +1040,7 @@ int link_request_set_routes(Link *link) {
assert(link->state != _LINK_STATE_INVALID); assert(link->state != _LINK_STATE_INVALID);
link->static_routes_configured = false; link->static_routes_configured = false;
link->static_routes_ready = false;
if (!link_has_carrier(link) && !link->network->configure_without_carrier) if (!link_has_carrier(link) && !link->network->configure_without_carrier)
/* During configuring addresses, the link lost its carrier. As networkd is dropping /* During configuring addresses, the link lost its carrier. As networkd is dropping
@ -1069,7 +1069,7 @@ int link_request_set_routes(Link *link) {
if (link->route_messages == 0) { if (link->route_messages == 0) {
link->static_routes_configured = true; link->static_routes_configured = true;
link_request_set_nexthop(link); link_check_ready(link);
} else { } else {
log_link_debug(link, "Setting routes"); log_link_debug(link, "Setting routes");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
@ -1085,107 +1085,70 @@ void link_check_ready(Link *link) {
assert(link); assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) { if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
log_link_debug(link, "%s(): link is in failed or linger state.", __func__);
return; return;
}
if (!link->network) if (!link->network)
return; return;
if (!link->addresses_configured) { if (!link->addresses_configured)
log_link_debug(link, "%s(): static addresses are not configured.", __func__);
return; return;
}
if (!link->neighbors_configured) { if (!link->neighbors_configured)
log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
return; return;
}
SET_FOREACH(a, link->addresses, i) SET_FOREACH(a, link->addresses, i)
if (!address_is_ready(a)) { if (!address_is_ready(a))
_cleanup_free_ char *str = NULL;
(void) in_addr_to_string(a->family, &a->in_addr, &str);
log_link_debug(link, "%s(): an address %s/%d is not ready.", __func__, strnull(str), a->prefixlen);
return; return;
}
if (!link->addresses_ready) { if (!link->addresses_ready) {
link->addresses_ready = true; link->addresses_ready = true;
r = link_request_set_routes(link); r = link_request_set_routes(link);
if (r < 0) if (r < 0)
link_enter_failed(link); link_enter_failed(link);
log_link_debug(link, "%s(): static addresses are configured. Configuring static routes.", __func__);
return; return;
} }
if (!link->static_routes_configured) { if (!link->static_routes_configured)
log_link_debug(link, "%s(): static routes are not configured.", __func__); return;
if (!link->static_routes_ready) {
link->static_routes_ready = true;
r = link_request_set_nexthop(link);
if (r < 0)
link_enter_failed(link);
return; return;
} }
if (!link->static_nexthops_configured) { if (!link->static_nexthops_configured)
log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
return; return;
}
if (!link->routing_policy_rules_configured) { if (!link->routing_policy_rules_configured)
log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
return; return;
}
if (!link->tc_configured) { if (!link->tc_configured)
log_link_debug(link, "%s(): traffic controls are not configured.", __func__);
return; return;
}
if (!link->sr_iov_configured) { if (!link->sr_iov_configured)
log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
return; return;
}
if (link_has_carrier(link) || !link->network->configure_without_carrier) { if (link_has_carrier(link) || !link->network->configure_without_carrier) {
if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address) { if (link_ipv4ll_enabled(link, ADDRESS_FAMILY_IPV4) && !link->ipv4ll_address)
log_link_debug(link, "%s(): IPv4LL is not configured.", __func__);
return; return;
}
if (link_ipv6ll_enabled(link) && if (link_ipv6ll_enabled(link) &&
in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address)) { in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address))
log_link_debug(link, "%s(): IPv6LL is not configured.", __func__);
return; return;
}
if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link)) && set_isempty(link->addresses)) { if ((link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link)) &&
log_link_debug(link, "%s(): DHCP4 or DHCP6 is enabled but no address is assigned yet.", __func__); !link->dhcp4_configured &&
!link->dhcp6_configured &&
!link->ndisc_configured &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address))
/* When DHCP or RA is enabled, at least one protocol must provide an address, or
* an IPv4ll fallback address must be configured. */
return; return;
}
if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || dhcp6_get_prefix_delegation(link) || link_ipv6_accept_ra_enabled(link)) {
if (!link->dhcp4_configured &&
!(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
!(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
!(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!(link_ipv4ll_enabled(link, ADDRESS_FAMILY_FALLBACK_IPV4) && link->ipv4ll_address)) {
/* When DHCP or RA is enabled, at least one protocol must provide an address, or
* an IPv4ll fallback address must be configured. */
log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
return;
}
log_link_debug(link, "%s(): dhcp4:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
__func__,
yes_no(link->dhcp4_configured),
yes_no(link->dhcp6_address_configured),
yes_no(link->dhcp6_route_configured),
yes_no(link->dhcp6_pd_address_configured),
yes_no(link->dhcp6_pd_route_configured),
yes_no(link->ndisc_addresses_configured),
yes_no(link->ndisc_routes_configured));
}
} }
if (link->state != LINK_STATE_CONFIGURED) if (link->state != LINK_STATE_CONFIGURED)
@ -1282,6 +1245,7 @@ static int link_request_set_addresses(Link *link) {
link->addresses_ready = false; link->addresses_ready = false;
link->neighbors_configured = false; link->neighbors_configured = false;
link->static_routes_configured = false; link->static_routes_configured = false;
link->static_routes_ready = false;
link->static_nexthops_configured = false; link->static_nexthops_configured = false;
link->routing_policy_rules_configured = false; link->routing_policy_rules_configured = false;

View File

@ -100,23 +100,13 @@ typedef struct Link {
char *lease_file; char *lease_file;
uint32_t original_mtu; uint32_t original_mtu;
unsigned dhcp4_messages; unsigned dhcp4_messages;
unsigned dhcp4_remove_messages;
unsigned dhcp6_address_messages;
unsigned dhcp6_route_messages;
unsigned dhcp6_pd_address_messages;
unsigned dhcp6_pd_route_messages;
bool dhcp4_route_failed:1; bool dhcp4_route_failed:1;
bool dhcp4_route_retrying:1; bool dhcp4_route_retrying:1;
bool dhcp4_configured:1; bool dhcp4_configured:1;
bool dhcp6_address_configured:1; bool dhcp6_configured:1;
bool dhcp6_route_configured:1;
bool dhcp6_pd_address_configured:1;
bool dhcp6_pd_route_configured:1;
unsigned ndisc_addresses_messages; unsigned ndisc_messages;
unsigned ndisc_routes_messages; bool ndisc_configured;
bool ndisc_addresses_configured:1;
bool ndisc_routes_configured:1;
sd_ipv4ll *ipv4ll; sd_ipv4ll *ipv4ll;
bool ipv4ll_address:1; bool ipv4ll_address:1;
@ -125,6 +115,7 @@ typedef struct Link {
bool addresses_ready:1; bool addresses_ready:1;
bool neighbors_configured:1; bool neighbors_configured:1;
bool static_routes_configured:1; bool static_routes_configured:1;
bool static_routes_ready:1;
bool static_nexthops_configured:1; bool static_nexthops_configured:1;
bool routing_policy_rules_configured:1; bool routing_policy_rules_configured:1;
bool tc_configured:1; bool tc_configured:1;
@ -226,6 +217,7 @@ uint32_t link_get_vrf_table(Link *link);
uint32_t link_get_dhcp_route_table(Link *link); uint32_t link_get_dhcp_route_table(Link *link);
uint32_t link_get_ipv6_accept_ra_route_table(Link *link); uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
int link_request_set_routes(Link *link); int link_request_set_routes(Link *link);
int link_request_set_nexthop(Link *link);
int link_reconfigure(Link *link, bool force); int link_reconfigure(Link *link, bool force);

View File

@ -82,60 +82,64 @@ static int make_stableprivate_address(Link *link, const struct in6_addr *prefix,
return 0; return 0;
} }
static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int ndisc_netlink_route_message_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
assert(link->ndisc_routes_messages > 0); assert(link->ndisc_messages > 0);
link->ndisc_routes_messages--; link->ndisc_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
log_link_message_error_errno(link, m, r, "Could not set NDisc route"); log_link_message_error_errno(link, m, r, "Could not set NDisc route or address");
link_enter_failed(link); link_enter_failed(link);
return 1; return 1;
} }
if (link->ndisc_routes_messages == 0) { if (link->ndisc_messages == 0) {
log_link_debug(link, "NDisc routes set."); link->ndisc_configured = true;
link->ndisc_routes_configured = true; r = link_request_set_routes(link);
if (r < 0) {
link_enter_failed(link);
return 1;
}
link_check_ready(link); link_check_ready(link);
} }
return 1; return 1;
} }
static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int ndisc_netlink_address_message_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
assert(link->ndisc_addresses_messages > 0); assert(link->ndisc_messages > 0);
link->ndisc_addresses_messages--; link->ndisc_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) { if (r < 0 && r != -EEXIST) {
log_link_message_error_errno(link, m, r, "Could not set NDisc address"); log_link_message_error_errno(link, m, r, "Could not set NDisc route or address");
link_enter_failed(link); link_enter_failed(link);
return 1; return 1;
} else if (r >= 0) } else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager); (void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->ndisc_addresses_messages == 0) { if (link->ndisc_messages == 0) {
log_link_debug(link, "NDisc SLAAC addresses set."); link->ndisc_configured = true;
link->ndisc_addresses_configured = true;
r = link_request_set_routes(link); r = link_request_set_routes(link);
if (r < 0) { if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
return 1; return 1;
} }
link_check_ready(link);
} }
return 1; return 1;
@ -219,14 +223,14 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->lifetime = time_now + lifetime * USEC_PER_SEC; route->lifetime = time_now + lifetime * USEC_PER_SEC;
route->mtu = mtu; route->mtu = mtu;
r = route_configure(route, link, ndisc_route_handler); r = route_configure(route, link, ndisc_netlink_route_message_handler);
if (r < 0) { if (r < 0) {
log_link_warning_errno(link, r, "Could not set default route: %m"); log_link_warning_errno(link, r, "Could not set default route: %m");
link_enter_failed(link); link_enter_failed(link);
return r; return r;
} }
if (r > 0) if (r > 0)
link->ndisc_routes_messages++; link->ndisc_messages++;
Route *route_gw; Route *route_gw;
LIST_FOREACH(routes, route_gw, link->network->static_routes) { LIST_FOREACH(routes, route_gw, link->network->static_routes) {
@ -238,14 +242,14 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route_gw->gw = gateway; route_gw->gw = gateway;
r = route_configure(route_gw, link, ndisc_route_handler); r = route_configure(route_gw, link, ndisc_netlink_route_message_handler);
if (r < 0) { if (r < 0) {
log_link_error_errno(link, r, "Could not set gateway: %m"); log_link_error_errno(link, r, "Could not set gateway: %m");
link_enter_failed(link); link_enter_failed(link);
return r; return r;
} }
if (r > 0) if (r > 0)
link->ndisc_routes_messages++; link->ndisc_messages++;
} }
return 0; return 0;
@ -400,19 +404,20 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
} else if (lifetime_valid > 0) } else if (lifetime_valid > 0)
a->cinfo.ifa_valid = lifetime_valid; a->cinfo.ifa_valid = lifetime_valid;
else else
continue; /* see RFC4862 section 5.5.3.d */ return 0; /* see RFC4862 section 5.5.3.d */
if (a->cinfo.ifa_valid == 0) if (a->cinfo.ifa_valid == 0)
continue; continue;
r = address_configure(a, link, ndisc_address_handler, true); r = address_configure(a, link, ndisc_netlink_address_message_handler, true);
if (r < 0) { if (r < 0) {
log_link_warning_errno(link, r, "Could not set SLAAC address: %m"); log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
link_enter_failed(link); link_enter_failed(link);
return r; return r;
} }
if (r > 0) if (r > 0)
link->ndisc_addresses_messages++; link->ndisc_messages++;
} }
return 0; return 0;
@ -456,14 +461,14 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m"); return log_link_error_errno(link, r, "Failed to get prefix address: %m");
r = route_configure(route, link, ndisc_route_handler); r = route_configure(route, link, ndisc_netlink_route_message_handler);
if (r < 0) { if (r < 0) {
log_link_warning_errno(link, r, "Could not set prefix route: %m"); log_link_warning_errno(link, r, "Could not set prefix route: %m");
link_enter_failed(link); link_enter_failed(link);
return r; return r;
} }
if (r > 0) if (r > 0)
link->ndisc_routes_messages++; link->ndisc_messages++;
return 0; return 0;
} }
@ -518,14 +523,14 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get route address: %m"); return log_link_error_errno(link, r, "Failed to get route address: %m");
r = route_configure(route, link, ndisc_route_handler); r = route_configure(route, link, ndisc_netlink_route_message_handler);
if (r < 0) { if (r < 0) {
log_link_warning_errno(link, r, "Could not set additional route: %m"); log_link_warning_errno(link, r, "Could not set additional route: %m");
link_enter_failed(link); link_enter_failed(link);
return r; return r;
} }
if (r > 0) if (r > 0)
link->ndisc_routes_messages++; link->ndisc_messages++;
return 0; return 0;
} }
@ -811,38 +816,11 @@ static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *r
switch (event) { switch (event) {
case SD_NDISC_EVENT_ROUTER: case SD_NDISC_EVENT_ROUTER:
link->ndisc_addresses_configured = false;
link->ndisc_routes_configured = false;
(void) ndisc_router_handler(link, rt); (void) ndisc_router_handler(link, rt);
if (link->ndisc_addresses_messages == 0)
link->ndisc_addresses_configured = true;
else {
log_link_debug(link, "Setting SLAAC addresses.");
/* address_handler calls link_request_set_routes() and link_request_set_nexthop().
* Before they are called, the related flags must be cleared. Otherwise, the link
* becomes configured state before routes are configured. */
link->static_routes_configured = false;
link->static_nexthops_configured = false;
}
if (link->ndisc_routes_messages == 0)
link->ndisc_routes_configured = true;
else
log_link_debug(link, "Setting NDisc routes.");
if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
link_check_ready(link);
else
link_set_state(link, LINK_STATE_CONFIGURING);
break; break;
case SD_NDISC_EVENT_TIMEOUT: case SD_NDISC_EVENT_TIMEOUT:
log_link_debug(link, "NDISC handler get timeout event"); link->ndisc_configured = true;
link->ndisc_addresses_configured = true;
link->ndisc_routes_configured = true;
link_check_ready(link); link_check_ready(link);
break; break;

View File

@ -52,7 +52,7 @@ void network_apply_anonymize_if_set(Network *network) {
/* RFC7844 section 3.6.: /* RFC7844 section 3.6.:
The client intending to protect its privacy SHOULD only request a The client intending to protect its privacy SHOULD only request a
minimal number of options in the PRL and SHOULD also randomly shuffle minimal number of options in the PRL and SHOULD also randomly shuffle
the ordering of option codes in the PRL. If this random ordering the ordering of option codes in the PRL. If this random ordering
cannot be implemented, the client MAY order the option codes in the cannot be implemented, the client MAY order the option codes in the
PRL by option code number (lowest to highest). PRL by option code number (lowest to highest).
*/ */

View File

@ -26,7 +26,7 @@ int tc_init(double *ret_ticks_in_usec, uint32_t *ret_hz) {
if (r < 4) if (r < 4)
return -EIO; return -EIO;
clock_factor = (double) clock_resolution / USEC_PER_SEC; clock_factor = (double) clock_resolution / USEC_PER_SEC;
ticks_in_usec = (double) ticks_to_usec / usec_to_ticks * clock_factor; ticks_in_usec = (double) ticks_to_usec / usec_to_ticks * clock_factor;
} }
@ -57,7 +57,7 @@ int tc_time_to_tick(usec_t t, uint32_t *ret) {
return 0; return 0;
} }
int parse_tc_percent(const char *s, uint32_t *percent) { int parse_tc_percent(const char *s, uint32_t *percent) {
int r; int r;
assert(s); assert(s);

View File

@ -323,7 +323,7 @@ int manager_new(Manager **ret, Hashmap *interfaces, char **ignore,
if (r < 0) if (r < 0)
return r; return r;
(void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); (void) sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
(void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); (void) sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
if (timeout > 0) { if (timeout > 0) {

View File

@ -4636,7 +4636,7 @@ static int run_container(
if (!barrier_place_and_sync(&barrier)) /* #5 */ if (!barrier_place_and_sync(&barrier)) /* #5 */
return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early."); return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Child died too early.");
/* At this point we have made use of the UID we picked, and thus nss-systemd/systemd-machined.service /* At this point we have made use of the UID we picked, and thus nss-mymachines
* will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */ * will make them appear in getpwuid(), thus we can release the /etc/passwd lock. */
etc_passwd_lock = safe_close(etc_passwd_lock); etc_passwd_lock = safe_close(etc_passwd_lock);

View File

@ -19,11 +19,15 @@
#include "nss-util.h" #include "nss-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "string-util.h" #include "string-util.h"
#include "user-util.h"
NSS_GETHOSTBYNAME_PROTOTYPES(mymachines); NSS_GETHOSTBYNAME_PROTOTYPES(mymachines);
NSS_GETPW_PROTOTYPES(mymachines); NSS_GETPW_PROTOTYPES(mymachines);
NSS_GETGR_PROTOTYPES(mymachines); NSS_GETGR_PROTOTYPES(mymachines);
#define HOST_UID_LIMIT ((uid_t) UINT32_C(0x10000))
#define HOST_GID_LIMIT ((gid_t) UINT32_C(0x10000))
static int count_addresses(sd_bus_message *m, int af, unsigned *ret) { static int count_addresses(sd_bus_message *m, int af, unsigned *ret) {
unsigned c = 0; unsigned c = 0;
int r; int r;
@ -398,7 +402,94 @@ enum nss_status _nss_mymachines_getpwnam_r(
char *buffer, size_t buflen, char *buffer, size_t buflen,
int *errnop) { int *errnop) {
return NSS_STATUS_NOTFOUND; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *p, *e, *machine;
uint32_t mapped;
uid_t uid;
size_t l;
int r;
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
assert(name);
assert(pwd);
p = startswith(name, "vu-");
if (!p)
return NSS_STATUS_NOTFOUND;
e = strrchr(p, '-');
if (!e || e == p)
return NSS_STATUS_NOTFOUND;
if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
return NSS_STATUS_NOTFOUND;
r = parse_uid(e + 1, &uid);
if (r < 0)
return NSS_STATUS_NOTFOUND;
machine = strndupa(p, e - p);
if (!machine_name_is_valid(machine))
return NSS_STATUS_NOTFOUND;
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
/* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve
* these UIDs, but that should be unproblematic as containers should never be able to connect to a bus
* running on the host. */
return NSS_STATUS_NOTFOUND;
if (avoid_deadlock()) {
r = -EDEADLK;
goto fail;
}
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = bus_call_method(bus, bus_machine_mgr, "MapFromMachineUser", &error, &reply, "su", machine, (uint32_t) uid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
return NSS_STATUS_NOTFOUND;
goto fail;
}
r = sd_bus_message_read(reply, "u", &mapped);
if (r < 0)
goto fail;
/* Refuse to work if the mapped address is in the host UID range, or if there was no mapping at all. */
if (mapped < HOST_UID_LIMIT || mapped == uid)
return NSS_STATUS_NOTFOUND;
l = strlen(name);
if (buflen < l+1) {
UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
memcpy(buffer, name, l+1);
pwd->pw_name = buffer;
pwd->pw_uid = mapped;
pwd->pw_gid = GID_NOBODY;
pwd->pw_gecos = buffer;
pwd->pw_passwd = (char*) "*"; /* locked */
pwd->pw_dir = (char*) "/";
pwd->pw_shell = (char*) NOLOGIN;
return NSS_STATUS_SUCCESS;
fail:
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
} }
enum nss_status _nss_mymachines_getpwuid_r( enum nss_status _nss_mymachines_getpwuid_r(
@ -407,16 +498,162 @@ enum nss_status _nss_mymachines_getpwuid_r(
char *buffer, size_t buflen, char *buffer, size_t buflen,
int *errnop) { int *errnop) {
return NSS_STATUS_NOTFOUND; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *machine;
uint32_t mapped;
int r;
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
if (!uid_is_valid(uid))
return NSS_STATUS_NOTFOUND;
/* We consider all uids < 65536 host uids */
if (uid < HOST_UID_LIMIT)
return NSS_STATUS_NOTFOUND;
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
if (avoid_deadlock()) {
r = -EDEADLK;
goto fail;
}
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = bus_call_method(bus, bus_machine_mgr, "MapToMachineUser", &error, &reply, "u", (uint32_t) uid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_USER_MAPPING))
return NSS_STATUS_NOTFOUND;
goto fail;
}
r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
if (r < 0)
goto fail;
if (mapped == uid)
return NSS_STATUS_NOTFOUND;
if (snprintf(buffer, buflen, "vu-%s-" UID_FMT, machine, (uid_t) mapped) >= (int) buflen) {
UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
pwd->pw_name = buffer;
pwd->pw_uid = uid;
pwd->pw_gid = GID_NOBODY;
pwd->pw_gecos = buffer;
pwd->pw_passwd = (char*) "*"; /* locked */
pwd->pw_dir = (char*) "/";
pwd->pw_shell = (char*) NOLOGIN;
return NSS_STATUS_SUCCESS;
fail:
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
} }
#pragma GCC diagnostic ignored "-Wsizeof-pointer-memaccess"
enum nss_status _nss_mymachines_getgrnam_r( enum nss_status _nss_mymachines_getgrnam_r(
const char *name, const char *name,
struct group *gr, struct group *gr,
char *buffer, size_t buflen, char *buffer, size_t buflen,
int *errnop) { int *errnop) {
return NSS_STATUS_NOTFOUND; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *p, *e, *machine;
uint32_t mapped;
uid_t gid;
size_t l;
int r;
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
assert(name);
assert(gr);
p = startswith(name, "vg-");
if (!p)
return NSS_STATUS_NOTFOUND;
e = strrchr(p, '-');
if (!e || e == p)
return NSS_STATUS_NOTFOUND;
if (e - p > HOST_NAME_MAX - 1) /* -1 for the last dash */
return NSS_STATUS_NOTFOUND;
r = parse_gid(e + 1, &gid);
if (r < 0)
return NSS_STATUS_NOTFOUND;
machine = strndupa(p, e - p);
if (!machine_name_is_valid(machine))
return NSS_STATUS_NOTFOUND;
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
if (avoid_deadlock()) {
r = -EDEADLK;
goto fail;
}
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = bus_call_method(bus, bus_machine_mgr, "MapFromMachineGroup", &error, &reply, "su", machine, (uint32_t) gid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
return NSS_STATUS_NOTFOUND;
goto fail;
}
r = sd_bus_message_read(reply, "u", &mapped);
if (r < 0)
goto fail;
if (mapped < HOST_GID_LIMIT || mapped == gid)
return NSS_STATUS_NOTFOUND;
l = sizeof(char*) + strlen(name) + 1;
if (buflen < l) {
UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
memzero(buffer, sizeof(char*));
strcpy(buffer + sizeof(char*), name);
gr->gr_name = buffer + sizeof(char*);
gr->gr_gid = mapped;
gr->gr_passwd = (char*) "*"; /* locked */
gr->gr_mem = (char**) buffer;
return NSS_STATUS_SUCCESS;
fail:
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
} }
enum nss_status _nss_mymachines_getgrgid_r( enum nss_status _nss_mymachines_getgrgid_r(
@ -425,5 +662,72 @@ enum nss_status _nss_mymachines_getgrgid_r(
char *buffer, size_t buflen, char *buffer, size_t buflen,
int *errnop) { int *errnop) {
return NSS_STATUS_NOTFOUND; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_(sd_bus_message_unrefp) sd_bus_message* reply = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
const char *machine;
uint32_t mapped;
int r;
PROTECT_ERRNO;
BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
if (!gid_is_valid(gid))
return NSS_STATUS_NOTFOUND;
/* We consider all gids < 65536 host gids */
if (gid < HOST_GID_LIMIT)
return NSS_STATUS_NOTFOUND;
if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
return NSS_STATUS_NOTFOUND;
if (avoid_deadlock()) {
r = -EDEADLK;
goto fail;
}
r = sd_bus_open_system(&bus);
if (r < 0)
goto fail;
r = bus_call_method(bus, bus_machine_mgr, "MapToMachineGroup", &error, &reply, "u", (uint32_t) gid);
if (r < 0) {
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_GROUP_MAPPING))
return NSS_STATUS_NOTFOUND;
goto fail;
}
r = sd_bus_message_read(reply, "sou", &machine, NULL, &mapped);
if (r < 0)
goto fail;
if (mapped == gid)
return NSS_STATUS_NOTFOUND;
if (buflen < sizeof(char*) + 1) {
UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
memzero(buffer, sizeof(char*));
if (snprintf(buffer + sizeof(char*), buflen - sizeof(char*), "vg-%s-" GID_FMT, machine, (gid_t) mapped) >= (int) buflen) {
UNPROTECT_ERRNO;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
gr->gr_name = buffer + sizeof(char*);
gr->gr_gid = gid;
gr->gr_passwd = (char*) "*"; /* locked */
gr->gr_mem = (char**) buffer;
return NSS_STATUS_SUCCESS;
fail:
UNPROTECT_ERRNO;
*errnop = -r;
return NSS_STATUS_UNAVAIL;
} }

View File

@ -50,7 +50,6 @@
static int print_catalog(FILE *f, sd_journal *j) { static int print_catalog(FILE *f, sd_journal *j) {
_cleanup_free_ char *t = NULL, *z = NULL; _cleanup_free_ char *t = NULL, *z = NULL;
const char *newline, *prefix;
int r; int r;
assert(j); assert(j);
@ -61,31 +60,13 @@ static int print_catalog(FILE *f, sd_journal *j) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to find catalog entry: %m"); return log_error_errno(r, "Failed to find catalog entry: %m");
if (is_locale_utf8()) z = strreplace(strstrip(t), "\n", "\n-- ");
prefix = strjoina(special_glyph(SPECIAL_GLYPH_LIGHT_SHADE), special_glyph(SPECIAL_GLYPH_LIGHT_SHADE));
else
prefix = "--";
if (colors_enabled())
newline = strjoina(ANSI_NORMAL "\n" ANSI_GREY, prefix, ANSI_NORMAL " " ANSI_GREEN);
else
newline = strjoina("\n", prefix, " ");
z = strreplace(strstrip(t), "\n", newline);
if (!z) if (!z)
return log_oom(); return log_oom();
if (colors_enabled()) fputs("-- ", f);
fprintf(f, ANSI_GREY "%s" ANSI_NORMAL " " ANSI_GREEN, prefix);
else
fprintf(f, "%s ", prefix);
fputs(z, f); fputs(z, f);
fputc('\n', f);
if (colors_enabled())
fputs(ANSI_NORMAL "\n", f);
else
fputc('\n', f);
return 1; return 1;
} }

View File

@ -156,8 +156,6 @@ static int userdb_on_query_reply(
r = -ESRCH; r = -ESRCH;
else if (streq(error_id, "io.systemd.UserDatabase.ServiceNotAvailable")) else if (streq(error_id, "io.systemd.UserDatabase.ServiceNotAvailable"))
r = -EHOSTDOWN; r = -EHOSTDOWN;
else if (streq(error_id, "io.systemd.UserDatabase.EnumerationNotSupported"))
r = -EOPNOTSUPP;
else if (streq(error_id, VARLINK_ERROR_TIMEOUT)) else if (streq(error_id, VARLINK_ERROR_TIMEOUT))
r = -ETIMEDOUT; r = -ETIMEDOUT;
else else

View File

@ -858,7 +858,7 @@ static void test_path_is_encrypted_one(const char *p, int expect) {
return; return;
assert_se(r >= 0); assert_se(r >= 0);
log_info("%s encrypted: %s", p, yes_no(r)); printf("%s encrypted: %s\n", p, yes_no(r));
assert_se(expect < 0 || ((r > 0) == (expect > 0))); assert_se(expect < 0 || ((r > 0) == (expect > 0)));
} }

View File

@ -1 +0,0 @@
../TEST-01-BASIC/Makefile

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -e
TEST_DESCRIPTION="test timer units when initial clock is ahead"
TEST_NO_NSPAWN=1
future_date=$(date -u +%Y-%m-%dT%H:%M:%S -d '+3 days')
QEMU_OPTIONS="-rtc base=${future_date}"
. $TEST_BASE_DIR/test-functions
do_test "$@" 53

View File

@ -376,7 +376,7 @@ DHCP={}
# IPv6, but we want to wait for both # IPv6, but we want to wait for both
for _ in range(10): for _ in range(10):
out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface]) out = subprocess.check_output(['ip', 'a', 'show', 'dev', self.iface])
if b'state UP' in out and b'inet6 2600' in out and b'inet 192.168' in out and b'tentative' not in out: if b'state UP' in out and b'inet6 2600' in out and b'inet 192.168' in out:
break break
time.sleep(1) time.sleep(1)
else: else:

View File

@ -1,5 +1,2 @@
[Match] [Match]
Name=bond199 Name=bond199
[Network]
IPv6AcceptRA=no

View File

@ -2,5 +2,4 @@
Name=veth-peer Name=veth-peer
[Network] [Network]
IPv6AcceptRA=no
EmitLLDP=yes EmitLLDP=yes

View File

@ -2,5 +2,4 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
KeepConfiguration=static KeepConfiguration=static

View File

@ -2,5 +2,4 @@
Name=veth99 Name=veth99
[Network] [Network]
IPv6AcceptRA=no
LLDP=yes LLDP=yes

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Address=192.168.42.100/24 Address=192.168.42.100/24
DNS=192.168.42.1 DNS=192.168.42.1
Domains= one two three four five six seven eight nine ten Domains= one two three four five six seven eight nine ten

View File

@ -3,6 +3,3 @@ Name=dummy98
[Link] [Link]
MACAddress=00:01:02:aa:bb:cc MACAddress=00:01:02:aa:bb:cc
[Network]
IPv6AcceptRA=no

View File

@ -2,8 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
# these lines are ignored # these lines are ignored
Address=hogehoge Address=hogehoge
Address=foofoo Address=foofoo

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=test1 Name=test1
[Network]
IPv6AcceptRA=no
[RoutingPolicyRule] [RoutingPolicyRule]
TypeOfService=0x08 TypeOfService=0x08
Table=7 Table=7

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=test1 Name=test1
[Network]
IPv6AcceptRA=no
[RoutingPolicyRule] [RoutingPolicyRule]
TypeOfService=0x08 TypeOfService=0x08
Table=7 Table=7

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=test1 Name=test1
[Network]
IPv6AcceptRA=no
[RoutingPolicyRule] [RoutingPolicyRule]
TypeOfService=0x08 TypeOfService=0x08
Table=7 Table=7

View File

@ -2,6 +2,5 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Address=149.10.124.58/28 Address=149.10.124.58/28
Gateway=149.10.124.60 Gateway=149.10.124.60

View File

@ -2,6 +2,5 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Address=149.10.124.58/28 Address=149.10.124.58/28
Gateway=149.10.124.59 Gateway=149.10.124.59

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=dummy98 Name=dummy98
[Network]
IPv6AcceptRA=no
[IPv6AddressLabel] [IPv6AddressLabel]
Label=4444 Label=4444
Prefix=2004:da8:1:0::/64 Prefix=2004:da8:1:0::/64

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
VRF=vrf99 VRF=vrf99
Address=192.168.100.2/24 Address=192.168.100.2/24
Gateway=192.168.100.1 Gateway=192.168.100.1

View File

@ -1,5 +1,2 @@
[Match] [Match]
Name=vrf99 Name=vrf99
[Network]
IPv6AcceptRA=no

View File

@ -2,5 +2,4 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=sittun99 Tunnel=sittun99

View File

@ -2,6 +2,5 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=erspan99 Tunnel=erspan99
Tunnel=erspan98 Tunnel=erspan98

View File

@ -2,6 +2,5 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=gretap99 Tunnel=gretap99
Tunnel=gretap98 Tunnel=gretap98

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=gretun99 Tunnel=gretun99
Tunnel=gretun98 Tunnel=gretun98
Tunnel=gretun97 Tunnel=gretun97

View File

@ -2,6 +2,5 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=ip6gretap99 Tunnel=ip6gretap99
Tunnel=ip6gretap98 Tunnel=ip6gretap98

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=ip6gretun99 Tunnel=ip6gretun99
Tunnel=ip6gretun98 Tunnel=ip6gretun98
Tunnel=ip6gretun97 Tunnel=ip6gretun97

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=ip6tnl99 Tunnel=ip6tnl99
Tunnel=ip6tnl98 Tunnel=ip6tnl98
Tunnel=ip6tnl97 Tunnel=ip6tnl97

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=ipiptun99 Tunnel=ipiptun99
Tunnel=ipiptun98 Tunnel=ipiptun98
Tunnel=ipiptun97 Tunnel=ipiptun97

View File

@ -2,5 +2,4 @@
Name=test1 Name=test1
[Network] [Network]
IPv6AcceptRA=no
IPVLAN=ipvlan99 IPVLAN=ipvlan99

View File

@ -2,5 +2,4 @@
Name=test1 Name=test1
[Network] [Network]
IPv6AcceptRA=no
IPVTAP=ipvtap99 IPVTAP=ipvtap99

View File

@ -2,5 +2,4 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=isataptun99 Tunnel=isataptun99

View File

@ -2,5 +2,4 @@
Name=test1 Name=test1
[Network] [Network]
IPv6AcceptRA=no
MACVLAN=macvlan99 MACVLAN=macvlan99

View File

@ -2,5 +2,4 @@
Name=test1 Name=test1
[Network] [Network]
IPv6AcceptRA=no
MACVTAP=macvtap99 MACVTAP=macvtap99

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=dummy98 Name=dummy98
[Network]
IPv6AcceptRA=no
[RoutingPolicyRule] [RoutingPolicyRule]
TypeOfService=0x08 TypeOfService=0x08
Table=8 Table=8

View File

@ -1,9 +1,6 @@
[Match] [Match]
Name=test1 Name=test1
[Network]
IPv6AcceptRA=no
[RoutingPolicyRule] [RoutingPolicyRule]
TypeOfService=0x08 TypeOfService=0x08
Table=7 Table=7

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=sittun99 Tunnel=sittun99
Tunnel=sittun98 Tunnel=sittun98
Tunnel=sittun97 Tunnel=sittun97

View File

@ -5,7 +5,6 @@ Name=dummy98
RequiredForOnline=routable RequiredForOnline=routable
[Network] [Network]
IPv6AcceptRA=no
DNS=10.10.10.10 10.10.10.11 DNS=10.10.10.10 10.10.10.11
NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org NTP=0.fedora.pool.ntp.org 1.fedora.pool.ntp.org
Domains=hogehoge ~foofoo Domains=hogehoge ~foofoo

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=vtitun99 Tunnel=vtitun99
Tunnel=vtitun98 Tunnel=vtitun98
Tunnel=vtitun97 Tunnel=vtitun97

View File

@ -2,7 +2,6 @@
Name=dummy98 Name=dummy98
[Network] [Network]
IPv6AcceptRA=no
Tunnel=vti6tun99 Tunnel=vti6tun99
Tunnel=vti6tun98 Tunnel=vti6tun98
Tunnel=vti6tun97 Tunnel=vti6tun97

View File

@ -557,7 +557,7 @@ class Utilities():
if i > 0: if i > 0:
time.sleep(1) time.sleep(1)
output = check_output(f'ip {ipv} address show dev {link} scope {scope}') output = check_output(f'ip {ipv} address show dev {link} scope {scope}')
if re.search(address_regex, output) and 'tentative' not in output: if re.search(address_regex, output):
break break
else: else:
self.assertRegex(output, address_regex) self.assertRegex(output, address_regex)
@ -3168,12 +3168,6 @@ class NetworkdDHCPClientTests(unittest.TestCase, Utilities):
self.assertRegex(output, '2600::') self.assertRegex(output, '2600::')
self.assertNotRegex(output, '192.168.5') self.assertNotRegex(output, '192.168.5')
output = check_output('ip addr show dev veth99')
print(output)
self.assertRegex(output, '2600::')
self.assertNotRegex(output, '192.168.5')
self.assertNotRegex(output, 'tentative')
# Confirm that ipv6 token is not set in the kernel # Confirm that ipv6 token is not set in the kernel
output = check_output('ip token show dev veth99') output = check_output('ip token show dev veth99')
print(output) print(output)

View File

@ -1,7 +0,0 @@
[Unit]
Description=TEST-53-ISSUE-16347
[Service]
ExecStartPre=rm -f /failed /testok
ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
Type=oneshot

View File

@ -1,30 +0,0 @@
#!/usr/bin/env bash
set -ex
set -o pipefail
>/failed
# Reset host date to current time, 3 days in the past.
date -s "-3 days"
# Run a timer for every 15 minutes.
systemd-run --unit test-timer --on-calendar "*:0/15:0" true
next_elapsed=$(systemctl show test-timer.timer -p NextElapseUSecRealtime --value)
next_elapsed=$(date -d "${next_elapsed}" +%s)
now=$(date +%s)
time_delta=$((next_elapsed - now))
# Check that the timer will elapse in less than 20 minutes.
((0 < time_delta && time_delta < 1200)) || {
echo 'Timer elapse outside of the expected 20 minute window.'
echo " next_elapsed=${next_elapsed}"
echo " now=${now}"
echo " time_delta=${time_delta}"
echo ''
} >>/failed
if test ! -s /failed ; then
rm -f /failed
touch /testok
fi