mirror of
https://github.com/systemd/systemd
synced 2026-03-26 16:54:53 +01:00
Compare commits
1 Commits
1feeb15a0c
...
72e79f88ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72e79f88ac |
3
NEWS
3
NEWS
@ -3868,9 +3868,6 @@ CHANGES WITH 240:
|
||||
Consult the kernel documentation for details on this sysctl:
|
||||
https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
|
||||
|
||||
* The v239 change to turn on "net.ipv4.tcp_ecn" by default has been
|
||||
reverted.
|
||||
|
||||
* CPUAccounting=yes no longer enables the CPU controller when using
|
||||
kernel 4.15+ and the unified cgroup hierarchy, as required accounting
|
||||
statistics are now provided independently from the CPU controller.
|
||||
|
||||
40
TODO
40
TODO
@ -83,8 +83,6 @@ Janitorial Clean-ups:
|
||||
|
||||
Features:
|
||||
|
||||
* PAM: pick auf one authentication token from credentials
|
||||
|
||||
* tpm2: figure out if we need to do anything for TPM2 parameter encryption? And
|
||||
if so, what precisely?
|
||||
|
||||
@ -94,6 +92,8 @@ Features:
|
||||
data in the image, make sure the image filename actually matches this, so
|
||||
that images cannot be misused.
|
||||
|
||||
* use credentials logic/TPM2 logic to store homed signing key
|
||||
|
||||
* New udev block device symlink names:
|
||||
/dev/disk/by-parttypelabel/<pttype>/<ptlabel>. Use case: if pt label is used
|
||||
as partition image version string, this is a safe way to reference a specific
|
||||
@ -1199,37 +1199,49 @@ Features:
|
||||
- when homed is in use, maybe start the user session manager in a mount namespace with MS_SLAVE,
|
||||
so that mounts propagate down but not up - eg, user A setting up a backup volume
|
||||
doesn't mean user B sees it
|
||||
- use credentials logic/TPM2 logic to store homed signing key
|
||||
- during login resize fs automatically towards size goal. Specifically,
|
||||
|
||||
* homed: during login resize fs automatically towards size goal. Specifically,
|
||||
resize to diskSize if possible, but leave a certain amount (configured by a
|
||||
new value diskLeaveFreeSize) of space free on the backing fs.
|
||||
- permit multiple user record signing keys to be used locally, and pick
|
||||
|
||||
* homed: permit multiple user record signing keys to be used locally, and pick
|
||||
the right one for signing records automatically depending on a pre-existing
|
||||
signature
|
||||
- add a way to "adopt" a home directory, i.e. strip foreign signatures
|
||||
|
||||
* homed: add a way to "adopt" a home directory, i.e. strip foreign signatures
|
||||
and insert a local signature instead.
|
||||
- as an extension to the directory+subvolume backend: if located on
|
||||
|
||||
* homed: as an extension to the directory+subvolume backend: if located on
|
||||
especially marked fs, then sync down password into LUKS header of that fs,
|
||||
and always verify passwords against it too. Bootstrapping is a problem
|
||||
though: if no one is logged in (or no other user even exists yet), how do you
|
||||
unlock the volume in order to create the first user and add the first pw.
|
||||
- support new FS_IOC_ADD_ENCRYPTION_KEY ioctl for setting up fscrypt
|
||||
- maybe pre-create ~/.cache as subvol so that it can have separate quota
|
||||
|
||||
* homed: support new FS_IOC_ADD_ENCRYPTION_KEY ioctl for setting up fscrypt
|
||||
|
||||
* homed: maybe pre-create ~/.cache as subvol so that it can have separate quota
|
||||
easily?
|
||||
- if kernel 5.12 uid mapping mounts exist, use that instead of recursive
|
||||
|
||||
* homed: if kernel 5.12 uid mapping mounts exist, use that instead of recursive
|
||||
chowns.
|
||||
- add a switch to homectl (maybe called --first-boot) where it will check if
|
||||
|
||||
* add a switch to homectl (maybe called --first-boot) where it will check if
|
||||
any non-system users exist, and if not prompts interactively for basic user
|
||||
info, mimicking systemd-firstboot. Then, place this in a service that runs
|
||||
after systemd-homed, but before gdm and friends, as a simple, barebones
|
||||
fallback logic to get a regular user created on uninitialized systems.
|
||||
- store PKCS#11 + FIDO2 token info in LUKS2 header, compatible with
|
||||
|
||||
* homed: store PKCS#11 + FIDO2 token info in LUKS2 header, compatible with
|
||||
systemd-cryptsetup, so that it can unlock homed volumes
|
||||
- try to unmount in regular intervals when home dir was busy when we
|
||||
|
||||
* homed: try to unmount in regular intervals when home dir was busy when we
|
||||
tried because idle.
|
||||
- keep an fd to the homedir open at all times, to keep the fs pinned
|
||||
|
||||
* homed: keep an fd to the homedir open at all times, to keep the fs pinned
|
||||
(autofs and such) while user is logged in.
|
||||
|
||||
* when we resize disks (homed?) always round up to 4K sectors, not 512K
|
||||
|
||||
* add a new switch --auto-definitions=yes/no or so to systemd-repart. If
|
||||
specified, synthesize a definition automatically if we can: enlarge last
|
||||
partition on disk, but only if it is marked for growing and not read-only.
|
||||
|
||||
@ -49,7 +49,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
|
||||
| `77055800-792c-4f94-b39a-98c91b762bb6` | _Root Partition (LoongArch 64-bit)_ | ditto | ditto |
|
||||
| `60d5a7fe-8e7d-435c-b714-3dd8162144e1` | _Root Partition (RISC-V 32-bit)_ | ditto | ditto |
|
||||
| `72ec70a6-cf74-40e6-bd49-4bda08e8f224` | _Root Partition (RISC-V 64-bit)_ | ditto | ditto |
|
||||
| `d13c5d3b-b5d1-422a-b29f-9454fdc89d76` | _Root Verity Partition (x86)_ | A dm-verity superblock followed by hash data | Contains dm-verity integrity hash data for the matching root partition. If this feature is used the partition UUID of the root partition should be the first 128 bits of the root hash of the dm-verity hash data, and the partition UUID of this dm-verity partition should be the final 128 bits of it, so that the root partition and its verity partition can be discovered easily, simply by specifying the root hash. |
|
||||
| `d13c5d3b-b5d1-422a-b29f-9454fdc89d76` | _Root Verity Partition (x86)_ | A dm-verity superblock followed by hash data | On systems with matching architecture, contains dm-verity integrity hash data for the matching root partition. If this feature is used the partition UUID of the root partition should be the first 128bit of the root hash of the dm-verity hash data, and the partition UUID of this dm-verity partition should be the final 128bit of it, so that the root partition and its verity partition can be discovered easily, simply by specifying the root hash. |
|
||||
| `2c7357ed-ebd2-46d9-aec1-23d437ec2bf5` | _Root Verity Partition (x86-64)_ | ditto | ditto |
|
||||
| `7386cdf2-203c-47a9-a498-f2ecce45a2d6` | _Root Verity Partition (32-bit ARM)_ | ditto | ditto |
|
||||
| `df3300ce-d69f-4c92-978c-9bfb0f38d820` | _Root Verity Partition (64-bit ARM/AArch64)_ | ditto | ditto |
|
||||
@ -75,7 +75,7 @@ Interface](https://systemd.io/BOOT_LOADER_INTERFACE).
|
||||
| `8f1056be-9b05-47c4-81d6-be53128e5b54` | _`/usr/` Verity Partition (RISC-V 64-bit)_ | ditto | ditto |
|
||||
| `933ac7e1-2eb4-4f13-b844-0e14e2aef915` | _Home Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/home/`. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/home`. |
|
||||
| `3b8f8425-20e0-4f3b-907f-1a25a76f98e8` | _Server Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/srv/`. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/srv`. |
|
||||
| `4d21b016-b534-45c2-a9fb-5c16e091fd2d` | _Variable Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/var/` — under the condition that its partition UUID matches the first 128 bits of `HMAC-SHA256(machine-id, 0x4d21b016b53445c2a9fb5c16e091fd2d)` (i.e. the SHA256 HMAC hash of the binary type UUID keyed by the machine ID as read from [`/etc/machine-id`](https://www.freedesktop.org/software/systemd/man/machine-id.html). This special requirement is made because `/var/` (unlike the other partition types listed here) is inherently private to a specific installation and cannot possibly be shared between multiple OS installations on the same disk, and thus should be bound to a specific instance of the OS, identified by its machine ID. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/var`. |
|
||||
| `4d21b016-b534-45c2-a9fb-5c16e091fd2d` | _Variable Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/var/` — under the condition that its partition UUID matches the first 128 bit of `HMAC-SHA256(machine-id, 0x4d21b016b53445c2a9fb5c16e091fd2d)` (i.e. the SHA256 HMAC hash of the binary type UUID keyed by the machine ID as read from [`/etc/machine-id`](https://www.freedesktop.org/software/systemd/man/machine-id.html). This special requirement is made because `/var/` (unlike the other partition types listed here) is inherently private to a specific installation and cannot possibly be shared between multiple OS installations on the same disk, and thus should be bound to a specific instance of the OS, identified by its machine ID. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/var`. |
|
||||
| `7ec6f557-3bc5-4aca-b293-16ef5df639d1` | _Temporary Data Partition_ | Any native, optionally in LUKS | The first partition with this type UUID on the disk containing the root partition is automatically mounted to `/var/tmp/`. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/tmp`. Note that the intended mount point is indeed `/var/tmp/`, not `/tmp/`. The latter is typically maintained in memory via <tt>tmpfs</tt> and does not require a partition on disk. In some cases it might be desirable to make `/tmp/` persistent too, in which case it is recommended to make it a symlink or bind mount to `/var/tmp/`, thus not requiring its own partition type UUID. |
|
||||
| `0657fd6d-a4ab-43c4-84e5-0933c84b4f4f` | _Swap_ | Swap, optionally in LUKS | All swap partitions on the disk containing the root partition are automatically enabled. If the partition is encrypted with LUKS, the device mapper file will be named `/dev/mapper/swap`. This partition type predates the Discoverable Partitions Specification. |
|
||||
| `0fc63daf-8483-4772-8e79-3d69d8477de4` | _Generic Linux Data Partitions_ | Any native, optionally in LUKS | No automatic mounting takes place for other Linux data partitions. This partition type should be used for all partitions that carry Linux file systems. The installer needs to mount them explicitly via entries in <tt>/etc/fstab</tt>. Optionally, these partitions may be encrypted with LUKS. This partition type predates the Discoverable Partitions Specification. |
|
||||
|
||||
@ -709,10 +709,6 @@ evdev:name:gpio-keys:phys:gpio-keys/input0:ev:3:dmi:*:svnHewlett-Packard:pnHPStr
|
||||
evdev:name:gpio-keys:phys:gpio-keys/input0:ev:23:dmi:*:svnHewlett-Packard:pnHPStream7Tablet:*
|
||||
KEYBOARD_KEY_0=unknown
|
||||
|
||||
# HP Omen 15
|
||||
evdev:atkbd:dmi:bvn*:bvr*:bd*:svnHP:pnOMENLaptop15*:pvr*
|
||||
KEYBOARD_KEY_a1=!calc
|
||||
|
||||
##########################################################
|
||||
# Huawei
|
||||
##########################################################
|
||||
|
||||
@ -240,10 +240,6 @@ sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo*:pnP1D6_C109K:*
|
||||
sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvrY13D_KB133.103:bd06/01/2018:svnHampoo:pnDefaultstring:pvrV100:rvnHampoo:rnY13D_KB133:rvrV100:cvnDefaultstring:ct9:cvrDefaultstring:*
|
||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
|
||||
|
||||
# Chuwi SurBook Mini (CWI540)
|
||||
sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo*:pnC3W6_AP108_4GB:*
|
||||
ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, 1, 0; 0, 0, 1
|
||||
|
||||
#########################################
|
||||
# Connect
|
||||
#########################################
|
||||
@ -407,16 +403,6 @@ sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd03/20/201
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/25/2017:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnAMICorporation:rnDefaultstring:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:*
|
||||
ACCEL_LOCATION=base
|
||||
|
||||
#########################################
|
||||
# Hometech
|
||||
########################################
|
||||
|
||||
# Nobody bothered to use Linux on any device of this manufacturer
|
||||
# so current marks might be too general and need fixes.
|
||||
# These values are based on Wi101 model.
|
||||
sensor:modalias:acpi:BMA250E*:dmi:*:svnInsyde*:pni101c:*
|
||||
ACCEL_MOUNT_MATRIX=0,1,0;-1,0,0;-1,0,0
|
||||
|
||||
#########################################
|
||||
# HP
|
||||
#########################################
|
||||
|
||||
31
hwdb.d/70-analysers.hwdb
Normal file
31
hwdb.d/70-analysers.hwdb
Normal file
@ -0,0 +1,31 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# Database for protocol analysers that should be accessible to the seat owner
|
||||
#
|
||||
# Permitted keys:
|
||||
# Specify if a device is a protocol analyser
|
||||
# ID_PROTOCOL_ANALYSER=1|0
|
||||
|
||||
###########################################################
|
||||
# Total Phase
|
||||
###########################################################
|
||||
# Aarvark I2C/SPI Host Adapter
|
||||
usb:v0403pe0d0d*
|
||||
ID_PROTOCOL_ANALYSER=1
|
||||
|
||||
# Beagle Protocol Analyzers
|
||||
usb:v1679p2001d*
|
||||
ID_PROTOCOL_ANALYSER=1
|
||||
|
||||
# Cheetah SPI Host Adapter
|
||||
usb:v1679p2002d*
|
||||
ID_PROTOCOL_ANALYSER=1
|
||||
|
||||
# Komodo CAN Duo Interface
|
||||
usb:v1679p3001d*
|
||||
ID_PROTOCOL_ANALYSER=1
|
||||
|
||||
# Power Delivery Analyzers
|
||||
usb:v1679p6003d*
|
||||
usb:v0483pdf11d*
|
||||
ID_PROTOCOL_ANALYSER=1
|
||||
@ -1,31 +0,0 @@
|
||||
# This file is part of systemd.
|
||||
#
|
||||
# Database for protocol analyzers that should be accessible to the seat owner
|
||||
#
|
||||
# Permitted keys:
|
||||
# Specify if a device is a protocol analyzer
|
||||
# ID_PROTOCOL_ANALYZER=1|0
|
||||
|
||||
###########################################################
|
||||
# Total Phase
|
||||
###########################################################
|
||||
# Aarvark I2C/SPI Host Adapter
|
||||
usb_device:v0403pe0d0*
|
||||
ID_PROTOCOL_ANALYZER=1
|
||||
|
||||
# Beagle Protocol Analyzers
|
||||
usb_device:v1679p2001*
|
||||
ID_PROTOCOL_ANALYZER=1
|
||||
|
||||
# Cheetah SPI Host Adapter
|
||||
usb_device:v1679p2002*
|
||||
ID_PROTOCOL_ANALYZER=1
|
||||
|
||||
# Komodo CAN Duo Interface
|
||||
usb_device:v1679p3001*
|
||||
ID_PROTOCOL_ANALYZER=1
|
||||
|
||||
# Power Delivery Analyzers
|
||||
usb_device:v1679p6003*
|
||||
usb_device:v0483pdf11*
|
||||
ID_PROTOCOL_ANALYZER=1
|
||||
@ -43,7 +43,6 @@
|
||||
# udevadm info /dev/input/eventXX.
|
||||
#
|
||||
# Allowed properties are:
|
||||
# ID_INPUT_POINTINGSTICK
|
||||
# POINTINGSTICK_CONST_ACCEL (deprecated)
|
||||
# POINTINGSTICK_SENSITIVITY
|
||||
#
|
||||
@ -79,12 +78,6 @@
|
||||
|
||||
# Sort by brand, model
|
||||
|
||||
##########################################
|
||||
# Generic
|
||||
##########################################
|
||||
evdev:name:*[tT]rack[pP]oint*:*
|
||||
ID_INPUT_POINTINGSTICK=1
|
||||
|
||||
#########################################
|
||||
# Dell
|
||||
#########################################
|
||||
|
||||
@ -27,7 +27,7 @@ hwdb_files_test = files('''
|
||||
60-keyboard.hwdb
|
||||
60-seat.hwdb
|
||||
60-sensor.hwdb
|
||||
70-analyzers.hwdb
|
||||
70-analysers.hwdb
|
||||
70-joystick.hwdb
|
||||
70-mouse.hwdb
|
||||
70-pointingstick.hwdb
|
||||
|
||||
@ -80,7 +80,6 @@ TYPES = {'mouse': ('usb', 'bluetooth', 'ps2', '*'),
|
||||
GENERAL_MATCHES = {'acpi',
|
||||
'bluetooth',
|
||||
'usb',
|
||||
'usb_device',
|
||||
'pci',
|
||||
'sdio',
|
||||
'vmbus',
|
||||
@ -148,7 +147,7 @@ def property_grammar():
|
||||
('ID_INPUT_TOUCHPAD', Or((Literal('0'), Literal('1')))),
|
||||
('ID_INPUT_TOUCHSCREEN', Or((Literal('0'), Literal('1')))),
|
||||
('ID_INPUT_TRACKBALL', Or((Literal('0'), Literal('1')))),
|
||||
('ID_PROTOCOL_ANALYZER', Or((Literal('0'), Literal('1')))),
|
||||
('ID_PROTOCOL_ANALYSER', Or((Literal('0'), Literal('1')))),
|
||||
('POINTINGSTICK_SENSITIVITY', INTEGER),
|
||||
('POINTINGSTICK_CONST_ACCEL', REAL),
|
||||
('ID_INPUT_JOYSTICK_INTEGRATION', Or(('internal', 'external'))),
|
||||
@ -208,9 +207,8 @@ def check_matches(groups):
|
||||
matches = sum((group[0] for group in groups), [])
|
||||
|
||||
# This is a partial check. The other cases could be also done, but those
|
||||
# three are most commonly wrong.
|
||||
# two are most commonly wrong.
|
||||
grammars = { 'usb' : 'v' + upperhex_word(4) + Optional('p' + upperhex_word(4)),
|
||||
'usb_device' : 'v' + upperhex_word(4) + Optional('p' + upperhex_word(4)),
|
||||
'pci' : 'v' + upperhex_word(8) + Optional('d' + upperhex_word(8)),
|
||||
}
|
||||
|
||||
|
||||
@ -93,36 +93,30 @@
|
||||
main system. Additionally, the presence of that file means that the system is in the initrd phase.
|
||||
<filename>/etc/os-release</filename> should be symlinked to <filename>/etc/initrd-release</filename>
|
||||
(or vice versa), so programs that only look for <filename>/etc/os-release</filename> (as described
|
||||
above) work correctly.</para>
|
||||
|
||||
<para>The rest of this document that talks about <filename>os-release</filename> should be understood
|
||||
to apply to <filename>initrd-release</filename> too.</para>
|
||||
above) work correctly. The rest of this document that talks about <filename>os-release</filename>
|
||||
should be understood to apply to <filename>initrd-release</filename> too.</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title><filename>/usr/lib/extension-release.d/extension-release.<replaceable>IMAGE</replaceable></filename></title>
|
||||
|
||||
<para><filename>/usr/lib/extension-release.d/extension-release.<replaceable>IMAGE</replaceable></filename>
|
||||
plays the same role for extension images as <filename>os-release</filename> for the main system, and
|
||||
follows the syntax and rules as described in the <ulink
|
||||
url="https://systemd.io/PORTABLE_SERVICES">Portable Services Documentation</ulink>. The purpose of this
|
||||
file is to identify the extension and to allow the operating system to verify that the extension image
|
||||
matches the base OS. This is typically implemented by checking that the <varname>ID=</varname> options
|
||||
match, and either <varname>SYSEXT_LEVEL=</varname> exists and matches too, or if it is not present,
|
||||
<varname>VERSION_ID=</varname> exists and matches. This ensures ABI/API compatibility between the
|
||||
layers and prevents merging of an incompatible image in an overlay.</para>
|
||||
|
||||
<para>In the <filename>extension-release.<replaceable>IMAGE</replaceable></filename> filename, the
|
||||
<replaceable>IMAGE</replaceable> part must exactly match the file name of the containing image with the
|
||||
suffix removed. In case it is not possible to guarantee that an image file name is stable and doesn't
|
||||
change between the build and the deployment phases, it is possible to relax this check: if exactly one
|
||||
file whose name matches <literal><filename>extension-release.*</filename></literal> is present in this
|
||||
directory, and the file is tagged with a <varname>user.extension-release.strict</varname>
|
||||
<citerefentry><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry> set to the
|
||||
string <literal>0</literal>, it will be used instead.</para>
|
||||
|
||||
<para>The rest of this document that talks about <filename>os-release</filename> should be understood
|
||||
to apply to <filename>extension-release</filename> too.</para>
|
||||
for extension images plays the same role as <filename>os-release</filename> in the main system, and follows the
|
||||
same syntax and rules as described in the <ulink url="https://systemd.io/PORTABLE_SERVICES">Portable Services Documentation</ulink>.
|
||||
The purpose of this file is to allow the operating system to correctly match an extension image
|
||||
to a base OS image, This is typically implemented by first checking that the <varname>ID=</varname>
|
||||
options match, and if they do either <varname>SYSEXT_LEVEL=</varname> has to match too (preferred), or
|
||||
as a fallback if that is not present <varname>VERSION_ID=</varname> is checked. This ensures that ABI/API
|
||||
between the layers matches and no incompatible images are merged in an overlay.
|
||||
It is preferred that the <filename>extension-release.<replaceable>IMAGE</replaceable></filename> filename is suffixed
|
||||
with the exact file name of the image that contains it, so that all such files in every layer of an overlay are visible.
|
||||
But for the purpose of parsing metadata, in case it is not possible to guarantee that an image file name is stable
|
||||
and doesn't change between the build and the deployment phases, the first and only file which name starts with
|
||||
<filename>extension-release.</filename>, is located in the same directory and is tagged with a
|
||||
<varname>user.extension-release.strict</varname> <citerefentry><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
set to the string <literal>0</literal>, will be parsed instead, if the one with the expected name cannot be found.
|
||||
The rest of this document that talks about <filename>os-release</filename> should be understood to apply to
|
||||
<filename>extension-release</filename> too.</para>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
|
||||
<para>During boot OS extension images are activated automatically, if the
|
||||
<filename>systemd-sysext.service</filename> is enabled. Note that this service runs only after the
|
||||
underlying file systems where system extensions may be located have been mounted. This means they are not
|
||||
underlying file systems where system extensions are searched are mounted. This means they are not
|
||||
suitable for shipping resources that are processed by subsystems running in earliest boot. Specifically,
|
||||
OS extension images are not suitable for shipping system services or
|
||||
<citerefentry><refentrytitle>systemd-sysusers</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
|
||||
@ -427,8 +427,7 @@
|
||||
has been unsuccessful for some time. (IPv4 link-local address autoconfiguration will usually
|
||||
happen in parallel with repeated attempts to acquire a DHCPv4 lease).</para>
|
||||
|
||||
<para>Defaults to <option>no</option> when <varname>Bridge=</varname> is set or when the specified
|
||||
<varname>MACVLAN=</varname>/<varname>MACVTAP=</varname> has <varname>Mode=passthru</varname>, or
|
||||
<para>Defaults to <option>no</option> when <varname>Bridge=yes</varname> is set, and
|
||||
<option>ipv6</option> otherwise.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -3830,7 +3830,7 @@ summary({
|
||||
# LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
|
||||
|
||||
if conf.get('ENABLE_EFI') == 1
|
||||
summary({'EFI arch' : efi_arch},
|
||||
summary({'efi arch' : efi_arch},
|
||||
section : 'Extensible Firmware Interface')
|
||||
|
||||
if have_gnu_efi
|
||||
|
||||
180
po/es.po
180
po/es.po
@ -4,15 +4,15 @@
|
||||
# Alex Puchades <alex94puchades@gmail.com>, 2015.
|
||||
# Daniel Mustieles <daniel.mustieles@gmail.com>, 2015.
|
||||
# Álex Puchades <alex94puchades@gmail.com>, 2015.
|
||||
# Adolfo Jayme Barrientos <fitoschido@gmail.com>, 2020, 2021.
|
||||
# Adolfo Jayme Barrientos <fitoschido@gmail.com>, 2020.
|
||||
# Emilio Herrera <ehespinosa57@gmail.com>, 2021.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: systemd master\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
|
||||
"PO-Revision-Date: 2021-08-26 18:05+0000\n"
|
||||
"Last-Translator: Adolfo Jayme Barrientos <fitoschido@gmail.com>\n"
|
||||
"PO-Revision-Date: 2021-06-08 09:04+0000\n"
|
||||
"Last-Translator: Emilio Herrera <ehespinosa57@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.fedoraproject.org/projects/systemd/"
|
||||
"master/es/>\n"
|
||||
"Language: es\n"
|
||||
@ -20,7 +20,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.8\n"
|
||||
"X-Generator: Weblate 4.6.2\n"
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:22
|
||||
msgid "Send passphrase back to system"
|
||||
@ -96,37 +96,40 @@ msgstr "Comprobar las credenciales de un área home"
|
||||
msgid ""
|
||||
"Authentication is required to check credentials against a user's home area."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para comprobar las credenciales del espacio personal "
|
||||
"de un usuario."
|
||||
"Se requiere autenticación para comprobar las credenciales contra un área "
|
||||
"home de usuario."
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:43
|
||||
msgid "Update a home area"
|
||||
msgstr "Actualizar un espacio personal"
|
||||
msgstr "Actualizar un área home"
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:44
|
||||
msgid "Authentication is required to update a user's home area."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para actualizar el espacio personal de un usuario."
|
||||
msgstr "Se requiere autenticación para actualizar un área home de usuario."
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:53
|
||||
msgid "Resize a home area"
|
||||
msgstr "Redimensionar un espacio personal"
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:54
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set a wall message"
|
||||
msgid "Authentication is required to resize a user's home area."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para redimensionar el espacio personal de un usuario."
|
||||
msgstr "Se requiere autenticación para establecer un muro de texto"
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:63
|
||||
msgid "Change password of a home area"
|
||||
msgstr "Cambiar contraseña de un espacio personal"
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:64
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Authentication is required to manage active sessions, users and seats."
|
||||
msgid ""
|
||||
"Authentication is required to change the password of a user's home area."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para cambiar la contraseña del espacio personal de un "
|
||||
"usuario."
|
||||
"Se requiere autenticación para administrar las sesiones activas, usuarios y "
|
||||
"puestos de trabajo."
|
||||
|
||||
#: src/hostname/org.freedesktop.hostname1.policy:20
|
||||
msgid "Set hostname"
|
||||
@ -158,11 +161,13 @@ msgstr "Necesita autenticarse para establecer la información de sistema local."
|
||||
|
||||
#: src/hostname/org.freedesktop.hostname1.policy:51
|
||||
msgid "Get product UUID"
|
||||
msgstr "Obtener UUID del producto"
|
||||
msgstr ""
|
||||
|
||||
#: src/hostname/org.freedesktop.hostname1.policy:52
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to reload '$(unit)'."
|
||||
msgid "Authentication is required to get product UUID."
|
||||
msgstr "Necesita autenticarse para obtener el UUID de un producto."
|
||||
msgstr "Se requiere autenticación para recargar '$(unit)'."
|
||||
|
||||
#: src/import/org.freedesktop.import1.policy:22
|
||||
msgid "Import a VM or container image"
|
||||
@ -577,12 +582,13 @@ msgstr "Necesita autenticarse para bloquear/desbloquear sesiones activas."
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:352
|
||||
msgid "Set the reboot \"reason\" in the kernel"
|
||||
msgstr "Establecer la «razón» de reinicio en el núcleo"
|
||||
msgstr ""
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:353
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system timezone."
|
||||
msgid "Authentication is required to set the reboot \"reason\" in the kernel."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para establecer la «razón» de reinicio en el núcleo."
|
||||
msgstr "Se requiere autenticación para establecer la zona horaria del sistema."
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:363
|
||||
#, fuzzy
|
||||
@ -601,27 +607,35 @@ msgstr ""
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:374
|
||||
msgid "Indicate to the boot loader to boot to the boot loader menu"
|
||||
msgstr "Indicar al cargador de arranque que inicie el menú de selección"
|
||||
msgstr ""
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:375
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Authentication is required to indicate to the firmware to boot to setup "
|
||||
#| "interface."
|
||||
msgid ""
|
||||
"Authentication is required to indicate to the boot loader to boot to the "
|
||||
"boot loader menu."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para indicar al cargador de arranque que inicie el "
|
||||
"menú de selección."
|
||||
"Se requiere autenticación para indicar al firmware que arranque la interfaz "
|
||||
"de configuración."
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:385
|
||||
msgid "Indicate to the boot loader to boot a specific entry"
|
||||
msgstr "Indicar al cargador de arranque que inicie una entrada concreta"
|
||||
msgstr ""
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:386
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Authentication is required to indicate to the firmware to boot to setup "
|
||||
#| "interface."
|
||||
msgid ""
|
||||
"Authentication is required to indicate to the boot loader to boot into a "
|
||||
"specific boot loader entry."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para indicar al cargador de arranque que inicie una "
|
||||
"entrada concreta."
|
||||
"Se requiere autenticación para indicar al firmware que arranque la interfaz "
|
||||
"de configuración."
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:396
|
||||
msgid "Set a wall message"
|
||||
@ -633,11 +647,13 @@ msgstr "Necesita autenticarse para establecer un muro de texto"
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:406
|
||||
msgid "Change Session"
|
||||
msgstr "Cambiar sesión"
|
||||
msgstr ""
|
||||
|
||||
#: src/login/org.freedesktop.login1.policy:407
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the local hostname."
|
||||
msgid "Authentication is required to change the virtual terminal."
|
||||
msgstr "Necesita autenticarse para cambiar la terminal virtual."
|
||||
msgstr "Se requiere autenticación para establecer el nombre del equipo local."
|
||||
|
||||
#: src/machine/org.freedesktop.machine1.policy:22
|
||||
msgid "Log into a local container"
|
||||
@ -649,11 +665,11 @@ msgstr "Necesita autenticarse para conectarse a un contenedor local."
|
||||
|
||||
#: src/machine/org.freedesktop.machine1.policy:32
|
||||
msgid "Log into the local host"
|
||||
msgstr "Acceder al anfitrión local"
|
||||
msgstr "Conectarse al equipo local"
|
||||
|
||||
#: src/machine/org.freedesktop.machine1.policy:33
|
||||
msgid "Authentication is required to log into the local host."
|
||||
msgstr "Necesita autenticarse para acceder al anfitrión local."
|
||||
msgstr "Necesita autenticarse para conectarse al equipo local."
|
||||
|
||||
#: src/machine/org.freedesktop.machine1.policy:42
|
||||
msgid "Acquire a shell in a local container"
|
||||
@ -718,145 +734,173 @@ msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:22
|
||||
msgid "Set NTP servers"
|
||||
msgstr "Establecer servidores NTP"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:23
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system time."
|
||||
msgid "Authentication is required to set NTP servers."
|
||||
msgstr "Necesita autenticarse para establecer servidores NTP."
|
||||
msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:33
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:44
|
||||
msgid "Set DNS servers"
|
||||
msgstr "Establecer servidores DNS"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:34
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:45
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system time."
|
||||
msgid "Authentication is required to set DNS servers."
|
||||
msgstr "Necesita autenticarse para establecer servidores DNS."
|
||||
msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:44
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:55
|
||||
msgid "Set domains"
|
||||
msgstr "Establecer dominios"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:45
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:56
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to stop '$(unit)'."
|
||||
msgid "Authentication is required to set domains."
|
||||
msgstr "Necesita autenticarse para establecer dominios."
|
||||
msgstr "Se requiere autenticación para detener '$(unit)'."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:55
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:66
|
||||
msgid "Set default route"
|
||||
msgstr "Establecer ruta predeterminada"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:56
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:67
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the local hostname."
|
||||
msgid "Authentication is required to set default route."
|
||||
msgstr "Necesita autenticarse para establecer la ruta predeterminada."
|
||||
msgstr "Se requiere autenticación para establecer el nombre del equipo local."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:66
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:77
|
||||
msgid "Enable/disable LLMNR"
|
||||
msgstr "Activar/desactivar LLMNR"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:67
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:78
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to hibernate the system."
|
||||
msgid "Authentication is required to enable or disable LLMNR."
|
||||
msgstr "Necesita autenticarse para activar o desactivar LLMNR."
|
||||
msgstr "Se requiere autenticación para hibernar el sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:77
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:88
|
||||
msgid "Enable/disable multicast DNS"
|
||||
msgstr "Activar/desactivar DNS multidifusión"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:78
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:89
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to log into the local host."
|
||||
msgid "Authentication is required to enable or disable multicast DNS."
|
||||
msgstr "Necesita autenticarse para activar o desactivar DNS multidifusión."
|
||||
msgstr "Se requiere autenticación para conectarse al equipo local."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:88
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:99
|
||||
msgid "Enable/disable DNS over TLS"
|
||||
msgstr "Activar/desactivar DNS por TLS"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:89
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:100
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the local hostname."
|
||||
msgid "Authentication is required to enable or disable DNS over TLS."
|
||||
msgstr "Necesita autenticarse para activar o desactivar DNS por TLS."
|
||||
msgstr "Se requiere autenticación para establecer el nombre del equipo local."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:99
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:110
|
||||
msgid "Enable/disable DNSSEC"
|
||||
msgstr "Activar/desactivar DNSSEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:100
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:111
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to hibernate the system."
|
||||
msgid "Authentication is required to enable or disable DNSSEC."
|
||||
msgstr "Necesita autenticarse para activar o desactivar DNSSEC."
|
||||
msgstr "Se requiere autenticación para hibernar el sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:110
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:121
|
||||
msgid "Set DNSSEC Negative Trust Anchors"
|
||||
msgstr "Establecer anclas de confianza negativas de DNSSEC"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:111
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:122
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system locale."
|
||||
msgid "Authentication is required to set DNSSEC Negative Trust Anchors."
|
||||
msgstr ""
|
||||
"Necesita autenticarse para establecer las anclas de confianza negativas de "
|
||||
"DNSSEC."
|
||||
msgstr "Se requiere autenticación para establecer la región del sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:121
|
||||
msgid "Revert NTP settings"
|
||||
msgstr "Revertir configuración de NTP"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:122
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system time."
|
||||
msgid "Authentication is required to reset NTP settings."
|
||||
msgstr "Necesita autenticarse para restablecer la configuración de NTP."
|
||||
msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:132
|
||||
msgid "Revert DNS settings"
|
||||
msgstr "Revertir configuración de DNS"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:133
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set the system time."
|
||||
msgid "Authentication is required to reset DNS settings."
|
||||
msgstr "Necesita autenticarse para restablecer la configuración de DNS."
|
||||
msgstr "Se requiere autenticación para establecer la fecha y hora del sistema."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:143
|
||||
msgid "DHCP server sends force renew message"
|
||||
msgstr "El servidor DCHP envía un mensaje de renovación forzada"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:144
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set a wall message"
|
||||
msgid "Authentication is required to send force renew message."
|
||||
msgstr "Necesita autenticarse para enviar el mensaje de renovación forzada."
|
||||
msgstr "Se requiere autenticación para establecer un muro de texto"
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:154
|
||||
msgid "Renew dynamic addresses"
|
||||
msgstr "Renovar direcciones dinámicas"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:155
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to set a wall message"
|
||||
msgid "Authentication is required to renew dynamic addresses."
|
||||
msgstr "Necesita autenticarse para renovar las direcciones dinámicas."
|
||||
msgstr "Se requiere autenticación para establecer un muro de texto"
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:165
|
||||
msgid "Reload network settings"
|
||||
msgstr "Recargar configuración de red"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:166
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to reload the systemd state."
|
||||
msgid "Authentication is required to reload network settings."
|
||||
msgstr "Necesita autenticarse para recargar la configuración de red."
|
||||
msgstr "Se requiere autenticación para recargar el estado de systemd."
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:176
|
||||
msgid "Reconfigure network interface"
|
||||
msgstr "Reconfigurar interfaz de red"
|
||||
msgstr ""
|
||||
|
||||
#: src/network/org.freedesktop.network1.policy:177
|
||||
#, fuzzy
|
||||
#| msgid "Authentication is required to reboot the system."
|
||||
msgid "Authentication is required to reconfigure network interface."
|
||||
msgstr "Necesita autenticarse para reconfigurar la interfaz de red."
|
||||
msgstr "Se requiere autenticación para reiniciar el sistema."
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:13
|
||||
msgid "Inspect a portable service image"
|
||||
msgstr "Inspeccionar una imagen de servicio portátil"
|
||||
msgstr ""
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:14
|
||||
#, fuzzy
|
||||
@ -868,7 +912,7 @@ msgstr ""
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:23
|
||||
msgid "Attach or detach a portable service image"
|
||||
msgstr "Adjuntar o desadjuntar una imagen de servicio portátil"
|
||||
msgstr ""
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:24
|
||||
#, fuzzy
|
||||
@ -881,7 +925,7 @@ msgstr ""
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:34
|
||||
msgid "Delete or modify portable service image"
|
||||
msgstr "Eliminar o modificar imagen de servicio portátil"
|
||||
msgstr ""
|
||||
|
||||
#: src/portable/org.freedesktop.portable1.policy:35
|
||||
#, fuzzy
|
||||
@ -894,7 +938,7 @@ msgstr ""
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:22
|
||||
msgid "Register a DNS-SD service"
|
||||
msgstr "Registrar un servicio DNS-SD"
|
||||
msgstr ""
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:23
|
||||
#, fuzzy
|
||||
@ -904,7 +948,7 @@ msgstr "Se requiere autenticación para establecer un muro de texto"
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:33
|
||||
msgid "Unregister a DNS-SD service"
|
||||
msgstr "Desregistrar un servicio DNS-SD"
|
||||
msgstr ""
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:34
|
||||
#, fuzzy
|
||||
@ -914,7 +958,7 @@ msgstr "Se requiere autenticación para establecer un muro de texto"
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:132
|
||||
msgid "Revert name resolution settings"
|
||||
msgstr "Revertir configuración de resolución de nombres"
|
||||
msgstr ""
|
||||
|
||||
#: src/resolve/org.freedesktop.resolve1.policy:133
|
||||
#, fuzzy
|
||||
|
||||
29
po/fi.po
29
po/fi.po
@ -7,7 +7,7 @@ msgstr ""
|
||||
"Project-Id-Version: systemd\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-01-08 17:48+0100\n"
|
||||
"PO-Revision-Date: 2021-08-26 18:05+0000\n"
|
||||
"PO-Revision-Date: 2021-08-23 18:04+0000\n"
|
||||
"Last-Translator: Jan Kuparinen <copper_fin@hotmail.com>\n"
|
||||
"Language-Team: Finnish <https://translate.fedoraproject.org/projects/systemd/"
|
||||
"master/fi/>\n"
|
||||
@ -20,52 +20,46 @@ msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:22
|
||||
msgid "Send passphrase back to system"
|
||||
msgstr "Lähetä tunnuslause takaisin järjestelmään"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:23
|
||||
msgid ""
|
||||
"Authentication is required to send the entered passphrase back to the system."
|
||||
msgstr ""
|
||||
"Todennus vaaditaan jotta syötetty tunnuslause lähetetään takaisin "
|
||||
"järjestelmään."
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:33
|
||||
msgid "Manage system services or other units"
|
||||
msgstr "Hallinnoi järjestelmäpalveluja tai muita yksiköitä"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:34
|
||||
msgid "Authentication is required to manage system services or other units."
|
||||
msgstr ""
|
||||
"Todennus vaaditaan järjestelmäpalvelujen tai muiden yksiköiden hallintaan."
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:43
|
||||
msgid "Manage system service or unit files"
|
||||
msgstr "Hallitse järjestelmäpalvelu- tai yksikkötiedostoja"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:44
|
||||
msgid "Authentication is required to manage system service or unit files."
|
||||
msgstr ""
|
||||
"Todennus vaaditaan järjestelmän palvelu- tai yksikkötiedostojen hallintaan."
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:54
|
||||
msgid "Set or unset system and service manager environment variables"
|
||||
msgstr "Aseta tai poista järjestelmän ja palvelunhallinnan ympäristömuuttujia"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:55
|
||||
msgid ""
|
||||
"Authentication is required to set or unset system and service manager "
|
||||
"environment variables."
|
||||
msgstr ""
|
||||
"Todennus vaaditaan järjestelmän ja palvelunhallinnan ympäristömuuttujien "
|
||||
"asettamiseen tai poistamiseen."
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:64
|
||||
msgid "Reload the systemd state"
|
||||
msgstr "Lataa järjestelmätila uudelleen"
|
||||
msgstr ""
|
||||
|
||||
#: src/core/org.freedesktop.systemd1.policy.in:65
|
||||
msgid "Authentication is required to reload the systemd state."
|
||||
msgstr "Todennus vaaditaan, jotta järjestelmätila voidaan ladata uudelleen."
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:13
|
||||
msgid "Create a home area"
|
||||
@ -73,25 +67,24 @@ msgstr "Luo kotialue"
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:14
|
||||
msgid "Authentication is required to create a user's home area."
|
||||
msgstr "Todennus vaaditaan käyttäjän kotialueen luomiseksi."
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:23
|
||||
msgid "Remove a home area"
|
||||
msgstr "Poista kotialue"
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:24
|
||||
msgid "Authentication is required to remove a user's home area."
|
||||
msgstr "Todennus vaaditaan käyttäjän kotialueen poistamiseksi."
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:33
|
||||
msgid "Check credentials of a home area"
|
||||
msgstr "Tarkista kotialueen valtuudet"
|
||||
msgstr ""
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:34
|
||||
msgid ""
|
||||
"Authentication is required to check credentials against a user's home area."
|
||||
msgstr ""
|
||||
"Todennus vaaditaan, jotta käyttäjän kotialueen valtuuksia voi tarkistaa."
|
||||
|
||||
#: src/home/org.freedesktop.home1.policy:43
|
||||
msgid "Update a home area"
|
||||
|
||||
@ -12,7 +12,6 @@ SUBSYSTEM=="rtc", KERNEL=="rtc0", SYMLINK+="rtc", OPTIONS+="link_priority=-100"
|
||||
|
||||
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id", IMPORT{builtin}="hwdb --subsystem=usb"
|
||||
ENV{MODALIAS}!="", IMPORT{builtin}="hwdb --subsystem=$env{SUBSYSTEM}"
|
||||
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="hwdb 'usb_device:v$attr{idVendor}p$attr{idProduct}:name:$attr{product}:'"
|
||||
|
||||
ACTION!="add", GOTO="default_end"
|
||||
|
||||
|
||||
@ -1,102 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _UAPI__LINUX_GENERIC_NETLINK_H
|
||||
#define _UAPI__LINUX_GENERIC_NETLINK_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#define GENL_NAMSIZ 16 /* length of family name */
|
||||
|
||||
#define GENL_MIN_ID NLMSG_MIN_TYPE
|
||||
#define GENL_MAX_ID 1023
|
||||
|
||||
struct genlmsghdr {
|
||||
__u8 cmd;
|
||||
__u8 version;
|
||||
__u16 reserved;
|
||||
};
|
||||
|
||||
#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
|
||||
|
||||
#define GENL_ADMIN_PERM 0x01
|
||||
#define GENL_CMD_CAP_DO 0x02
|
||||
#define GENL_CMD_CAP_DUMP 0x04
|
||||
#define GENL_CMD_CAP_HASPOL 0x08
|
||||
#define GENL_UNS_ADMIN_PERM 0x10
|
||||
|
||||
/*
|
||||
* List of reserved static generic netlink identifiers:
|
||||
*/
|
||||
#define GENL_ID_CTRL NLMSG_MIN_TYPE
|
||||
#define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1)
|
||||
#define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2)
|
||||
/* must be last reserved + 1 */
|
||||
#define GENL_START_ALLOC (NLMSG_MIN_TYPE + 3)
|
||||
|
||||
/**************************************************************************
|
||||
* Controller
|
||||
**************************************************************************/
|
||||
|
||||
enum {
|
||||
CTRL_CMD_UNSPEC,
|
||||
CTRL_CMD_NEWFAMILY,
|
||||
CTRL_CMD_DELFAMILY,
|
||||
CTRL_CMD_GETFAMILY,
|
||||
CTRL_CMD_NEWOPS,
|
||||
CTRL_CMD_DELOPS,
|
||||
CTRL_CMD_GETOPS,
|
||||
CTRL_CMD_NEWMCAST_GRP,
|
||||
CTRL_CMD_DELMCAST_GRP,
|
||||
CTRL_CMD_GETMCAST_GRP, /* unused */
|
||||
CTRL_CMD_GETPOLICY,
|
||||
__CTRL_CMD_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_UNSPEC,
|
||||
CTRL_ATTR_FAMILY_ID,
|
||||
CTRL_ATTR_FAMILY_NAME,
|
||||
CTRL_ATTR_VERSION,
|
||||
CTRL_ATTR_HDRSIZE,
|
||||
CTRL_ATTR_MAXATTR,
|
||||
CTRL_ATTR_OPS,
|
||||
CTRL_ATTR_MCAST_GROUPS,
|
||||
CTRL_ATTR_POLICY,
|
||||
CTRL_ATTR_OP_POLICY,
|
||||
CTRL_ATTR_OP,
|
||||
__CTRL_ATTR_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_OP_UNSPEC,
|
||||
CTRL_ATTR_OP_ID,
|
||||
CTRL_ATTR_OP_FLAGS,
|
||||
__CTRL_ATTR_OP_MAX,
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_MCAST_GRP_UNSPEC,
|
||||
CTRL_ATTR_MCAST_GRP_NAME,
|
||||
CTRL_ATTR_MCAST_GRP_ID,
|
||||
__CTRL_ATTR_MCAST_GRP_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
CTRL_ATTR_POLICY_UNSPEC,
|
||||
CTRL_ATTR_POLICY_DO,
|
||||
CTRL_ATTR_POLICY_DUMP,
|
||||
|
||||
__CTRL_ATTR_POLICY_DUMP_MAX,
|
||||
CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1
|
||||
};
|
||||
|
||||
#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
|
||||
|
||||
|
||||
#endif /* _UAPI__LINUX_GENERIC_NETLINK_H */
|
||||
@ -83,7 +83,6 @@ basic_sources = files('''
|
||||
linux/can/vxcan.h
|
||||
linux/fib_rules.h
|
||||
linux/fou.h
|
||||
linux/genetlink.h
|
||||
linux/hdlc/ioctl.h
|
||||
linux/if.h
|
||||
linux/if_addr.h
|
||||
|
||||
@ -630,11 +630,7 @@ static int check_x_access(const char *path, int *ret_fd) {
|
||||
return r;
|
||||
|
||||
r = access_fd(fd, X_OK);
|
||||
if (r == -ENOSYS) {
|
||||
/* /proc is not mounted. Fallback to access(). */
|
||||
if (access(path, X_OK) < 0)
|
||||
return -errno;
|
||||
} else if (r < 0)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_fd)
|
||||
@ -643,17 +639,22 @@ static int check_x_access(const char *path, int *ret_fd) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int find_executable_impl(const char *name, const char *root, char **ret_filename, int *ret_fd) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_free_ char *path_name = NULL;
|
||||
int r;
|
||||
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd) {
|
||||
int last_error, r;
|
||||
const char *p = NULL;
|
||||
|
||||
assert(name);
|
||||
|
||||
/* Function chase_symlinks() is invoked only when root is not NULL, as using it regardless of
|
||||
* root value would alter the behavior of existing callers for example: /bin/sleep would become
|
||||
* /usr/bin/sleep when find_executables is called. Hence, this function should be invoked when
|
||||
* needed to avoid unforeseen regression or other complicated changes. */
|
||||
if (is_path(name)) {
|
||||
_cleanup_close_ int fd = -1;
|
||||
_cleanup_free_ char *path_name = NULL;
|
||||
|
||||
/* Function chase_symlinks() is invoked only when root is not NULL,
|
||||
* as using it regardless of root value would alter the behavior
|
||||
* of existing callers for example: /bin/sleep would become
|
||||
* /usr/bin/sleep when find_executables is called. Hence, this function
|
||||
* should be invoked when needed to avoid unforeseen regression or other
|
||||
* complicated changes. */
|
||||
if (root) {
|
||||
r = chase_symlinks(name,
|
||||
root,
|
||||
@ -680,16 +681,7 @@ static int find_executable_impl(const char *name, const char *root, char **ret_f
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd) {
|
||||
int last_error, r;
|
||||
const char *p = NULL;
|
||||
|
||||
assert(name);
|
||||
|
||||
if (is_path(name))
|
||||
return find_executable_impl(name, root, ret_filename, ret_fd);
|
||||
}
|
||||
|
||||
if (use_path_envvar)
|
||||
/* Plain getenv, not secure_getenv, because we want to actually allow the user to pick the
|
||||
@ -703,6 +695,7 @@ int find_executable_full(const char *name, const char *root, bool use_path_envva
|
||||
/* Resolve a single-component name to a full path */
|
||||
for (;;) {
|
||||
_cleanup_free_ char *element = NULL;
|
||||
_cleanup_close_ int fd = -1;
|
||||
|
||||
r = extract_first_word(&p, &element, ":", EXTRACT_RELAX|EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||
if (r < 0)
|
||||
@ -716,7 +709,24 @@ int find_executable_full(const char *name, const char *root, bool use_path_envva
|
||||
if (!path_extend(&element, name))
|
||||
return -ENOMEM;
|
||||
|
||||
r = find_executable_impl(element, root, ret_filename, ret_fd);
|
||||
if (root) {
|
||||
char *path_name;
|
||||
|
||||
r = chase_symlinks(element,
|
||||
root,
|
||||
CHASE_PREFIX_ROOT,
|
||||
&path_name,
|
||||
/* ret_fd= */ NULL);
|
||||
if (r < 0) {
|
||||
if (r != -EACCES)
|
||||
last_error = r;
|
||||
continue;
|
||||
}
|
||||
|
||||
free_and_replace(element, path_name);
|
||||
}
|
||||
|
||||
r = check_x_access(element, ret_fd ? &fd : NULL);
|
||||
if (r < 0) {
|
||||
/* PATH entries which we don't have access to are ignored, as per tradition. */
|
||||
if (r != -EACCES)
|
||||
@ -725,6 +735,11 @@ int find_executable_full(const char *name, const char *root, bool use_path_envva
|
||||
}
|
||||
|
||||
/* Found it! */
|
||||
if (ret_filename)
|
||||
*ret_filename = path_simplify(TAKE_PTR(element));
|
||||
if (ret_fd)
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -813,6 +813,12 @@ static int automount_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1058,21 +1064,6 @@ static bool automount_supported(void) {
|
||||
return supported;
|
||||
}
|
||||
|
||||
static int automount_test_start_limit(Unit *u) {
|
||||
Automount *a = AUTOMOUNT(u);
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
automount_enter_dead(a, AUTOMOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
|
||||
[AUTOMOUNT_SUCCESS] = "success",
|
||||
[AUTOMOUNT_FAILURE_RESOURCES] = "resources",
|
||||
@ -1135,6 +1126,4 @@ const UnitVTable automount_vtable = {
|
||||
[JOB_FAILED] = "Failed to unset automount %s.",
|
||||
},
|
||||
},
|
||||
|
||||
.test_start_limit = automount_test_start_limit,
|
||||
};
|
||||
|
||||
@ -705,39 +705,8 @@ static void job_emit_done_message(Unit *u, uint32_t job_id, JobType t, JobResult
|
||||
|
||||
if (!console_only) { /* Skip printing if output goes to the console, and job_print_status_message()
|
||||
* will actually print something to the console. */
|
||||
Condition *c;
|
||||
const char *mid = job_done_mid(t, result); /* mid may be NULL. log_unit_struct() will ignore it. */
|
||||
|
||||
c = t == JOB_START && result == JOB_DONE ? unit_find_failed_condition(u) : NULL;
|
||||
if (c) {
|
||||
/* Special case units that were skipped because of a failed condition check so that
|
||||
* we can add more information to the message. */
|
||||
if (c->trigger)
|
||||
log_unit_struct(
|
||||
u,
|
||||
job_done_messages[result].log_level,
|
||||
"MESSAGE=%s was skipped because all trigger condition checks failed.",
|
||||
ident,
|
||||
"JOB_ID=%" PRIu32, job_id,
|
||||
"JOB_TYPE=%s", job_type_to_string(t),
|
||||
"JOB_RESULT=%s", job_result_to_string(result),
|
||||
LOG_UNIT_INVOCATION_ID(u),
|
||||
mid);
|
||||
else
|
||||
log_unit_struct(
|
||||
u,
|
||||
job_done_messages[result].log_level,
|
||||
"MESSAGE=%s was skipped because of a failed condition check (%s=%s%s).",
|
||||
ident,
|
||||
condition_type_to_string(c->type),
|
||||
c->negate ? "!" : "",
|
||||
c->parameter,
|
||||
"JOB_ID=%" PRIu32, job_id,
|
||||
"JOB_TYPE=%s", job_type_to_string(t),
|
||||
"JOB_RESULT=%s", job_result_to_string(result),
|
||||
LOG_UNIT_INVOCATION_ID(u),
|
||||
mid);
|
||||
} else {
|
||||
const char *mid = job_done_mid(t, result); /* mid may be NULL. log_unit_struct() will ignore it. */
|
||||
const char *msg_fmt = strjoina("MESSAGE=", format);
|
||||
|
||||
DISABLE_WARNING_FORMAT_NONLITERAL;
|
||||
@ -750,7 +719,6 @@ static void job_emit_done_message(Unit *u, uint32_t job_id, JobType t, JobResult
|
||||
mid);
|
||||
REENABLE_WARNING;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_console) {
|
||||
if (log_get_show_color())
|
||||
|
||||
@ -4115,7 +4115,7 @@ static void manager_unref_uid_internal(
|
||||
/* A generic implementation, covering both manager_unref_uid() and manager_unref_gid(), under the assumption
|
||||
* that uid_t and gid_t are actually defined the same way, with the same validity rules.
|
||||
*
|
||||
* We store a hashmap where the key is the UID/GID and the value is a 32bit reference counter, whose highest
|
||||
* We store a hashmap where the UID/GID is they key and the value is a 32bit reference counter, whose highest
|
||||
* bit is used as flag for marking UIDs/GIDs whose IPC objects to remove when the last reference to the UID/GID
|
||||
* is dropped. The flag is set to on, once at least one reference from a unit where RemoveIPC= is set is added
|
||||
* on a UID/GID. It is reset when the UID's/GID's reference counter drops to 0 again. */
|
||||
|
||||
@ -1167,6 +1167,12 @@ static int mount_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(m->state, MOUNT_DEAD, MOUNT_FAILED));
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2132,21 +2138,6 @@ static int mount_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&m->exec_context, ret);
|
||||
}
|
||||
|
||||
static int mount_test_start_limit(Unit *u) {
|
||||
Mount *m = MOUNT(u);
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const mount_exec_command_table[_MOUNT_EXEC_COMMAND_MAX] = {
|
||||
[MOUNT_EXEC_MOUNT] = "ExecMount",
|
||||
[MOUNT_EXEC_UNMOUNT] = "ExecUnmount",
|
||||
@ -2244,6 +2235,4 @@ const UnitVTable mount_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out unmounting %s.",
|
||||
},
|
||||
},
|
||||
|
||||
.test_start_limit = mount_test_start_limit,
|
||||
};
|
||||
|
||||
@ -590,6 +590,12 @@ static int path_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -806,21 +812,6 @@ static void path_reset_failed(Unit *u) {
|
||||
p->result = PATH_SUCCESS;
|
||||
}
|
||||
|
||||
static int path_test_start_limit(Unit *u) {
|
||||
Path *p = PATH(u);
|
||||
int r;
|
||||
|
||||
assert(p);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
path_enter_dead(p, PATH_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const path_type_table[_PATH_TYPE_MAX] = {
|
||||
[PATH_EXISTS] = "PathExists",
|
||||
[PATH_EXISTS_GLOB] = "PathExistsGlob",
|
||||
@ -875,6 +866,4 @@ const UnitVTable path_vtable = {
|
||||
.reset_failed = path_reset_failed,
|
||||
|
||||
.bus_set_property = bus_path_set_property,
|
||||
|
||||
.test_start_limit = path_test_start_limit,
|
||||
};
|
||||
|
||||
@ -2436,6 +2436,13 @@ static int service_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(s->state, SERVICE_DEAD, SERVICE_FAILED));
|
||||
|
||||
/* Make sure we don't enter a busy loop of some kind. */
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -4438,22 +4445,6 @@ static const char *service_finished_job(Unit *u, JobType t, JobResult result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int service_test_start_limit(Unit *u) {
|
||||
Service *s = SERVICE(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Make sure we don't enter a busy loop of some kind. */
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
service_enter_dead(s, SERVICE_FAILURE_START_LIMIT_HIT, false);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
[SERVICE_RESTART_NO] = "no",
|
||||
[SERVICE_RESTART_ON_SUCCESS] = "on-success",
|
||||
@ -4617,6 +4608,4 @@ const UnitVTable service_vtable = {
|
||||
},
|
||||
.finished_job = service_finished_job,
|
||||
},
|
||||
|
||||
.test_start_limit = service_test_start_limit,
|
||||
};
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
#include "process-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "serialize.h"
|
||||
#include "service.h"
|
||||
#include "signal-util.h"
|
||||
#include "smack-util.h"
|
||||
#include "socket.h"
|
||||
@ -2513,6 +2512,12 @@ static int socket_start(Unit *u) {
|
||||
|
||||
assert(IN_SET(s->state, SOCKET_DEAD, SOCKET_FAILED));
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -3419,21 +3424,6 @@ static int socket_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
static int socket_test_start_limit(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
socket_enter_dead(s, SOCKET_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
||||
[SOCKET_EXEC_START_PRE] = "ExecStartPre",
|
||||
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
|
||||
@ -3560,6 +3550,4 @@ const UnitVTable socket_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out stopping %s.",
|
||||
},
|
||||
},
|
||||
|
||||
.test_start_limit = socket_test_start_limit,
|
||||
};
|
||||
|
||||
@ -5,6 +5,7 @@ typedef struct Socket Socket;
|
||||
typedef struct SocketPeer SocketPeer;
|
||||
|
||||
#include "mount.h"
|
||||
#include "service.h"
|
||||
#include "socket-util.h"
|
||||
#include "unit.h"
|
||||
|
||||
|
||||
@ -932,6 +932,12 @@ static int swap_start(Unit *u) {
|
||||
if (UNIT(other)->job && UNIT(other)->job->state == JOB_RUNNING)
|
||||
return -EAGAIN;
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1582,21 +1588,6 @@ static int swap_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return exec_context_get_clean_mask(&s->exec_context, ret);
|
||||
}
|
||||
|
||||
static int swap_test_start_limit(Unit *u) {
|
||||
Swap *s = SWAP(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
swap_enter_dead(s, SWAP_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const swap_exec_command_table[_SWAP_EXEC_COMMAND_MAX] = {
|
||||
[SWAP_EXEC_ACTIVATE] = "ExecActivate",
|
||||
[SWAP_EXEC_DEACTIVATE] = "ExecDeactivate",
|
||||
@ -1692,6 +1683,4 @@ const UnitVTable swap_vtable = {
|
||||
[JOB_TIMEOUT] = "Timed out deactivating swap %s.",
|
||||
},
|
||||
},
|
||||
|
||||
.test_start_limit = swap_test_start_limit,
|
||||
};
|
||||
|
||||
@ -627,6 +627,12 @@ static int timer_start(Unit *u) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_acquire_invocation_id(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -884,21 +890,6 @@ static int timer_can_clean(Unit *u, ExecCleanMask *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer_test_start_limit(Unit *u) {
|
||||
Timer *t = TIMER(u);
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
r = unit_test_start_limit(u);
|
||||
if (r < 0) {
|
||||
timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* const timer_base_table[_TIMER_BASE_MAX] = {
|
||||
[TIMER_ACTIVE] = "OnActiveSec",
|
||||
[TIMER_BOOT] = "OnBootSec",
|
||||
@ -958,6 +949,4 @@ const UnitVTable timer_vtable = {
|
||||
.timezone_change = timer_timezone_change,
|
||||
|
||||
.bus_set_property = bus_timer_set_property,
|
||||
|
||||
.test_start_limit = timer_test_start_limit,
|
||||
};
|
||||
|
||||
@ -1727,7 +1727,7 @@ static bool unit_test_condition(Unit *u) {
|
||||
r = manager_get_effective_environment(u->manager, &env);
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(u, r, "Failed to determine effective environment: %m");
|
||||
u->condition_result = true;
|
||||
u->condition_result = CONDITION_ERROR;
|
||||
} else
|
||||
u->condition_result = condition_test_list(
|
||||
u->conditions,
|
||||
@ -1857,13 +1857,6 @@ int unit_start(Unit *u) {
|
||||
|
||||
assert(u);
|
||||
|
||||
/* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
|
||||
if (UNIT_VTABLE(u)->test_start_limit) {
|
||||
int r = UNIT_VTABLE(u)->test_start_limit(u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
|
||||
* is not startable by the user. This is relied on to detect when we need to wait for units and when
|
||||
* waiting is finished. */
|
||||
@ -5848,25 +5841,6 @@ int unit_thaw_vtable_common(Unit *u) {
|
||||
return unit_cgroup_freezer_action(u, FREEZER_THAW);
|
||||
}
|
||||
|
||||
Condition *unit_find_failed_condition(Unit *u) {
|
||||
Condition *c, *failed_trigger = NULL;
|
||||
bool has_succeeded_trigger = false;
|
||||
|
||||
if (u->condition_result)
|
||||
return NULL;
|
||||
|
||||
LIST_FOREACH(conditions, c, u->conditions)
|
||||
if (c->trigger) {
|
||||
if (c->result == CONDITION_SUCCEEDED)
|
||||
has_succeeded_trigger = true;
|
||||
else if (!failed_trigger)
|
||||
failed_trigger = c;
|
||||
} else if (c->result != CONDITION_SUCCEEDED)
|
||||
return c;
|
||||
|
||||
return failed_trigger && !has_succeeded_trigger ? failed_trigger : NULL;
|
||||
}
|
||||
|
||||
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
|
||||
[COLLECT_INACTIVE] = "inactive",
|
||||
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
|
||||
|
||||
@ -658,10 +658,6 @@ typedef struct UnitVTable {
|
||||
* of this type will immediately fail. */
|
||||
bool (*supported)(void);
|
||||
|
||||
/* If this function is set, it's invoked first as part of starting a unit to allow start rate
|
||||
* limiting checks to occur before we do anything else. */
|
||||
int (*test_start_limit)(Unit *u);
|
||||
|
||||
/* The strings to print in status messages */
|
||||
UnitStatusMessageFormats status_message_formats;
|
||||
|
||||
@ -984,8 +980,6 @@ void unit_thawed(Unit *u);
|
||||
int unit_freeze_vtable_common(Unit *u);
|
||||
int unit_thaw_vtable_common(Unit *u);
|
||||
|
||||
Condition *unit_find_failed_condition(Unit *u);
|
||||
|
||||
/* Macros which append UNIT= or USER_UNIT= to the message */
|
||||
|
||||
#define log_unit_full_errno_zerook(unit, level, error, ...) \
|
||||
|
||||
@ -299,8 +299,6 @@ static int module_callback(Dwfl_Module *mod, void **userdata, const char *name,
|
||||
program_header->p_offset,
|
||||
program_header->p_filesz,
|
||||
ELF_T_NHDR);
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
Elf *memelf = elf_memory(data->d_buf, data->d_size);
|
||||
if (!memelf)
|
||||
|
||||
@ -20,6 +20,7 @@ int acquire_luks2_key(
|
||||
int r;
|
||||
Fido2EnrollFlags required;
|
||||
size_t cid_size, salt_size, decrypted_key_size;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||
_cleanup_free_ void *cid = NULL, *salt = NULL;
|
||||
_cleanup_free_ char *rp_id = NULL;
|
||||
_cleanup_(erase_and_freep) void *decrypted_key = NULL;
|
||||
@ -52,7 +53,7 @@ int acquire_luks2_key(
|
||||
required,
|
||||
&decrypted_key,
|
||||
&decrypted_key_size);
|
||||
if (r == -ENOLCK) /* libcryptsetup returns -ENOANO also on wrong PIN */
|
||||
if (r == -ENOLCK) /* libcryptsetup returns -ENOANO also on wrong pin */
|
||||
r = -ENOANO;
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -60,7 +61,7 @@ int acquire_luks2_key(
|
||||
/* Before using this key as passphrase we base64 encode it, for compat with homed */
|
||||
r = base64mem(decrypted_key, decrypted_key_size, &base64_encoded);
|
||||
if (r < 0)
|
||||
return crypt_log_error_errno(cd, r, "Failed to base64 encode key: %m");
|
||||
return crypt_log_error_errno(cd, r, "Can not base64 encode key: %m");
|
||||
|
||||
*ret_keyslot_passphrase = TAKE_PTR(base64_encoded);
|
||||
*ret_keyslot_passphrase_size = strlen(*ret_keyslot_passphrase);
|
||||
|
||||
@ -38,18 +38,10 @@
|
||||
#include "strv.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
/* Round down to the nearest 4K size. Given that newer hardware generally prefers 4K sectors, let's align our
|
||||
* partitions to that too. In the worst case we'll waste 3.5K per partition that way, but I think I can live
|
||||
* with that. */
|
||||
#define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(4095))
|
||||
|
||||
/* Rounds up to the nearest 4K boundary. Returns UINT64_MAX on overflow */
|
||||
#define DISK_SIZE_ROUND_UP(x) \
|
||||
({ \
|
||||
uint64_t _x = (x); \
|
||||
_x > UINT64_MAX - 4095U ? UINT64_MAX : (_x + 4095U) & ~UINT64_C(4095); \
|
||||
})
|
||||
|
||||
/* Round down to the nearest 1K size. Note that Linux generally handles block devices with 512 blocks only,
|
||||
* but actually doesn't accept uneven numbers in many cases. To avoid any confusion around this we'll
|
||||
* strictly round disk sizes down to the next 1K boundary. */
|
||||
#define DISK_SIZE_ROUND_DOWN(x) ((x) & ~UINT64_C(1023))
|
||||
|
||||
int run_mark_dirty(int fd, bool b) {
|
||||
char x = '1';
|
||||
@ -1628,7 +1620,7 @@ static int make_partition_table(
|
||||
_cleanup_(fdisk_unref_parttypep) struct fdisk_parttype *t = NULL;
|
||||
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
|
||||
_cleanup_free_ char *path = NULL, *disk_uuid_as_string = NULL;
|
||||
uint64_t offset, size, first_lba, start, last_lba, end;
|
||||
uint64_t offset, size;
|
||||
sd_id128_t disk_uuid;
|
||||
int r;
|
||||
|
||||
@ -1668,31 +1660,17 @@ static int make_partition_table(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set partition type: %m");
|
||||
|
||||
r = fdisk_partition_start_follow_default(p, 1);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to place partition at beginning of space: %m");
|
||||
|
||||
r = fdisk_partition_partno_follow_default(p, 1);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to place partition at first free partition index: %m");
|
||||
|
||||
first_lba = fdisk_get_first_lba(c); /* Boundary where usable space starts */
|
||||
assert(first_lba <= UINT64_MAX/512);
|
||||
start = DISK_SIZE_ROUND_UP(first_lba * 512); /* Round up to multiple of 4K */
|
||||
|
||||
if (start == UINT64_MAX)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Overflow while rounding up start LBA.");
|
||||
|
||||
last_lba = fdisk_get_last_lba(c); /* One sector before boundary where usable space ends */
|
||||
assert(last_lba < UINT64_MAX/512);
|
||||
end = DISK_SIZE_ROUND_DOWN((last_lba + 1) * 512); /* Round down to multiple of 4K */
|
||||
|
||||
if (end <= start)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Resulting partition size zero or negative.");
|
||||
|
||||
r = fdisk_partition_set_start(p, start / 512);
|
||||
r = fdisk_partition_end_follow_default(p, 1);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to place partition at offset %" PRIu64 ": %m", start);
|
||||
|
||||
r = fdisk_partition_set_size(p, (end - start) / 512);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to end partition at offset %" PRIu64 ": %m", end);
|
||||
return log_error_errno(r, "Failed to make partition cover all free space: %m");
|
||||
|
||||
r = fdisk_partition_set_name(p, label);
|
||||
if (r < 0)
|
||||
@ -2714,8 +2692,6 @@ int home_resize_luks(
|
||||
|
||||
new_image_size = old_image_size; /* we can't resize physical block devices */
|
||||
} else {
|
||||
uint64_t new_image_size_rounded;
|
||||
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Image %s is not a block device nor regular file: %m", ip);
|
||||
@ -2726,16 +2702,11 @@ int home_resize_luks(
|
||||
* apply onto the loopback file as a whole. When we operate on block devices we instead apply
|
||||
* to the partition itself only. */
|
||||
|
||||
new_image_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size);
|
||||
|
||||
if (old_image_size == h->disk_size ||
|
||||
old_image_size == new_image_size_rounded) {
|
||||
/* If exact match, or a match after we rounded down, don't do a thing */
|
||||
new_image_size = DISK_SIZE_ROUND_DOWN(h->disk_size);
|
||||
if (new_image_size == old_image_size) {
|
||||
log_info("Image size already matching, skipping operation.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_image_size = new_image_size_rounded;
|
||||
}
|
||||
|
||||
r = home_prepare_luks(h, already_activated, whole_disk, cache, setup, &header_home);
|
||||
@ -2759,21 +2730,15 @@ int home_resize_luks(
|
||||
if (new_image_size <= partition_table_extra)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "New size smaller than partition table metadata.");
|
||||
|
||||
new_partition_size = DISK_SIZE_ROUND_DOWN(new_image_size - partition_table_extra);
|
||||
new_partition_size = new_image_size - partition_table_extra;
|
||||
} else {
|
||||
uint64_t new_partition_size_rounded;
|
||||
|
||||
assert(S_ISBLK(st.st_mode));
|
||||
|
||||
new_partition_size_rounded = DISK_SIZE_ROUND_DOWN(h->disk_size);
|
||||
|
||||
if (h->disk_size == setup->partition_size ||
|
||||
new_partition_size_rounded == setup->partition_size) {
|
||||
new_partition_size = DISK_SIZE_ROUND_DOWN(h->disk_size);
|
||||
if (new_partition_size == setup->partition_size) {
|
||||
log_info("Partition size already matching, skipping operation.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_partition_size = new_partition_size_rounded;
|
||||
}
|
||||
|
||||
if ((UINT64_MAX - setup->partition_offset) < new_partition_size ||
|
||||
@ -2787,7 +2752,7 @@ int home_resize_luks(
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "New size smaller than crypto payload offset?");
|
||||
|
||||
old_fs_size = (setup->partition_size / 512U - crypto_offset) * 512U;
|
||||
new_fs_size = DISK_SIZE_ROUND_DOWN((new_partition_size / 512U - crypto_offset) * 512U);
|
||||
new_fs_size = (new_partition_size / 512U - crypto_offset) * 512U;
|
||||
|
||||
/* Before we start doing anything, let's figure out if we actually can */
|
||||
resize_type = can_resize_fs(setup->root_fd, old_fs_size, new_fs_size);
|
||||
|
||||
@ -43,7 +43,7 @@ static int help(void) {
|
||||
" --version Show package version\n"
|
||||
" -s --strict When updating, return non-zero exit value on any parsing error\n"
|
||||
" --usr Generate in " UDEVLIBEXECDIR " instead of /etc/udev\n"
|
||||
" -r --root=PATH Alternative root path in the filesystem\n"
|
||||
" -r --root=PATH Alternative root path in the filesystem\n\n"
|
||||
"\nSee the %s for details.\n",
|
||||
program_invocation_short_name,
|
||||
ansi_highlight(),
|
||||
|
||||
@ -132,23 +132,19 @@ libsystemd_sources = files('''
|
||||
sd-device/sd-device.c
|
||||
sd-hwdb/hwdb-internal.h
|
||||
sd-hwdb/sd-hwdb.c
|
||||
sd-netlink/netlink-genl.c
|
||||
sd-netlink/netlink-genl.h
|
||||
sd-netlink/generic-netlink.c
|
||||
sd-netlink/generic-netlink.h
|
||||
sd-netlink/netlink-internal.h
|
||||
sd-netlink/netlink-message-nfnl.c
|
||||
sd-netlink/netlink-message-rtnl.c
|
||||
sd-netlink/netlink-message.c
|
||||
sd-netlink/netlink-slot.c
|
||||
sd-netlink/netlink-slot.h
|
||||
sd-netlink/netlink-socket.c
|
||||
sd-netlink/netlink-types-genl.c
|
||||
sd-netlink/netlink-types-internal.h
|
||||
sd-netlink/netlink-types-nfnl.c
|
||||
sd-netlink/netlink-types-rtnl.c
|
||||
sd-netlink/netlink-types.c
|
||||
sd-netlink/netlink-types.h
|
||||
sd-netlink/netlink-util.c
|
||||
sd-netlink/netlink-util.h
|
||||
sd-netlink/nfnl-message.c
|
||||
sd-netlink/rtnl-message.c
|
||||
sd-netlink/sd-netlink.c
|
||||
sd-network/network-util.c
|
||||
sd-network/network-util.h
|
||||
|
||||
179
src/libsystemd/sd-netlink/generic-netlink.c
Normal file
179
src/libsystemd/sd-netlink/generic-netlink.c
Normal file
@ -0,0 +1,179 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "generic-netlink.h"
|
||||
#include "netlink-internal.h"
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
uint8_t version;
|
||||
} genl_family;
|
||||
|
||||
static const genl_family genl_families[] = {
|
||||
[SD_GENL_ID_CTRL] = { .name = "", .version = 1 },
|
||||
[SD_GENL_WIREGUARD] = { .name = "wireguard", .version = 1 },
|
||||
[SD_GENL_FOU] = { .name = "fou", .version = 1 },
|
||||
[SD_GENL_L2TP] = { .name = "l2tp", .version = 1 },
|
||||
[SD_GENL_MACSEC] = { .name = "macsec", .version = 1 },
|
||||
[SD_GENL_NL80211] = { .name = "nl80211", .version = 1 },
|
||||
[SD_GENL_BATADV] = { .name = "batadv", .version = 1 },
|
||||
};
|
||||
|
||||
int sd_genl_socket_open(sd_netlink **ret) {
|
||||
return netlink_open_family(ret, NETLINK_GENERIC);
|
||||
}
|
||||
|
||||
static int genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *genl_cmd_type, *nl_type;
|
||||
const NLTypeSystem *type_system;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = message_new_empty(nl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(sizeof(struct genlmsghdr));
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
type_get_type_system(genl_cmd_type, &type_system);
|
||||
|
||||
r = type_system_get_type(type_system, &nl_type, cmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = nlmsg_type;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
|
||||
*(struct genlmsghdr *) NLMSG_DATA(m->hdr) = (struct genlmsghdr) {
|
||||
.cmd = cmd,
|
||||
.version = genl_families[family].version,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lookup_nlmsg_type(sd_netlink *nl, sd_genl_family_t family, uint16_t *ret) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
uint16_t u;
|
||||
void *v;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
if (family == SD_GENL_ID_CTRL) {
|
||||
*ret = GENL_ID_CTRL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
v = hashmap_get(nl->genl_family_to_nlmsg_type, INT_TO_PTR(family));
|
||||
if (v) {
|
||||
*ret = PTR_TO_UINT(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = genl_message_new(nl, SD_GENL_ID_CTRL, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, genl_families[family].name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u16(reply, CTRL_ATTR_FAMILY_ID, &u);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_to_nlmsg_type, NULL, INT_TO_PTR(family), UINT_TO_PTR(u));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->nlmsg_type_to_genl_family, NULL, UINT_TO_PTR(u), INT_TO_PTR(family));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = u;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret) {
|
||||
uint16_t nlmsg_type = 0; /* Unnecessary initialization to appease gcc */
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = lookup_nlmsg_type(nl, family, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_message_new(nl, family, nlmsg_type, cmd, ret);
|
||||
}
|
||||
|
||||
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t nlmsg_type, sd_genl_family_t *ret) {
|
||||
void *p;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
if (nlmsg_type == NLMSG_ERROR)
|
||||
*ret = SD_GENL_ERROR;
|
||||
else if (nlmsg_type == NLMSG_DONE)
|
||||
*ret = SD_GENL_DONE;
|
||||
else if (nlmsg_type == GENL_ID_CTRL)
|
||||
*ret = SD_GENL_ID_CTRL;
|
||||
else {
|
||||
p = hashmap_get(nl->nlmsg_type_to_genl_family, UINT_TO_PTR(nlmsg_type));
|
||||
if (!p)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret = PTR_TO_INT(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret) {
|
||||
uint16_t nlmsg_type;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return nlmsg_type_to_genl_family(nl, nlmsg_type, ret);
|
||||
}
|
||||
6
src/libsystemd/sd-netlink/generic-netlink.h
Normal file
6
src/libsystemd/sd-netlink/generic-netlink.h
Normal file
@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_family_t *ret);
|
||||
@ -1,473 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/genetlink.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-types.h"
|
||||
|
||||
typedef struct GenericNetlinkFamily {
|
||||
sd_netlink *genl;
|
||||
|
||||
const NLTypeSystem *type_system;
|
||||
|
||||
uint16_t id; /* a.k.a nlmsg_type */
|
||||
char *name;
|
||||
uint32_t version;
|
||||
uint32_t additional_header_size;
|
||||
Hashmap *multicast_group_by_name;
|
||||
} GenericNetlinkFamily;
|
||||
|
||||
static const GenericNetlinkFamily nlctrl_static = {
|
||||
.id = GENL_ID_CTRL,
|
||||
.name = (char*) CTRL_GENL_NAME,
|
||||
.version = 0x01,
|
||||
};
|
||||
|
||||
static GenericNetlinkFamily *genl_family_free(GenericNetlinkFamily *f) {
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
if (f->genl) {
|
||||
if (f->id > 0)
|
||||
hashmap_remove(f->genl->genl_family_by_id, UINT_TO_PTR(f->id));
|
||||
if (f->name)
|
||||
hashmap_remove(f->genl->genl_family_by_name, f->name);
|
||||
}
|
||||
|
||||
free(f->name);
|
||||
hashmap_free(f->multicast_group_by_name);
|
||||
|
||||
return mfree(f);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(GenericNetlinkFamily*, genl_family_free);
|
||||
|
||||
void genl_clear_family(sd_netlink *nl) {
|
||||
assert(nl);
|
||||
|
||||
nl->genl_family_by_name = hashmap_free_with_destructor(nl->genl_family_by_name, genl_family_free);
|
||||
nl->genl_family_by_id = hashmap_free_with_destructor(nl->genl_family_by_id, genl_family_free);
|
||||
}
|
||||
|
||||
static int genl_family_new(
|
||||
sd_netlink *nl,
|
||||
const char *expected_family_name,
|
||||
const NLTypeSystem *type_system,
|
||||
sd_netlink_message *message,
|
||||
const GenericNetlinkFamily **ret) {
|
||||
|
||||
_cleanup_(genl_family_freep) GenericNetlinkFamily *f = NULL;
|
||||
const char *family_name;
|
||||
uint8_t cmd;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(expected_family_name);
|
||||
assert(type_system);
|
||||
assert(message);
|
||||
assert(ret);
|
||||
|
||||
f = new(GenericNetlinkFamily, 1);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
*f = (GenericNetlinkFamily) {
|
||||
.type_system = type_system,
|
||||
};
|
||||
|
||||
if (sd_netlink_message_is_error(message)) {
|
||||
int e;
|
||||
|
||||
/* Kernel does not support the genl family? To prevent from resolving the family name
|
||||
* again, let's store the family with zero id to indicate that. */
|
||||
|
||||
e = sd_netlink_message_get_errno(message);
|
||||
if (e >= 0) /* Huh? */
|
||||
e = -EOPNOTSUPP;
|
||||
|
||||
f->name = strdup(expected_family_name);
|
||||
if (!f->name)
|
||||
return e;
|
||||
|
||||
if (hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f) < 0)
|
||||
return e;
|
||||
|
||||
f->genl = nl;
|
||||
TAKE_PTR(f);
|
||||
return e;
|
||||
}
|
||||
|
||||
r = sd_genl_message_get_family_name(nl, message, &family_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(family_name, CTRL_GENL_NAME))
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_genl_message_get_command(nl, message, &cmd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (cmd != CTRL_CMD_NEWFAMILY)
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_netlink_message_read_u16(message, CTRL_ATTR_FAMILY_ID, &f->id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, CTRL_ATTR_FAMILY_NAME, &f->name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!streq(f->name, expected_family_name))
|
||||
return -EINVAL;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_VERSION, &f->version);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_HDRSIZE, &f->additional_header_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_enter_container(message, CTRL_ATTR_MCAST_GROUPS);
|
||||
if (r >= 0) {
|
||||
for (uint16_t i = 0; i < UINT16_MAX; i++) {
|
||||
_cleanup_free_ char *group_name = NULL;
|
||||
uint32_t group_id;
|
||||
|
||||
r = sd_netlink_message_enter_array(message, i + 1);
|
||||
if (r == -ENODATA)
|
||||
break;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_u32(message, CTRL_ATTR_MCAST_GRP_ID, &group_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_string_strdup(message, CTRL_ATTR_MCAST_GRP_NAME, &group_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (group_id == 0) {
|
||||
log_debug("sd-netlink: received multicast group '%s' for generic netlink family '%s' with id == 0, ignoring",
|
||||
group_name, f->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(&f->multicast_group_by_name, &string_hash_ops_free, group_name, UINT32_TO_PTR(group_id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(group_name);
|
||||
}
|
||||
|
||||
r = sd_netlink_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_id, NULL, UINT_TO_PTR(f->id), f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_ensure_put(&nl->genl_family_by_name, &string_hash_ops, f->name, f);
|
||||
if (r < 0) {
|
||||
hashmap_remove(nl->genl_family_by_id, UINT_TO_PTR(f->id));
|
||||
return r;
|
||||
}
|
||||
|
||||
f->genl = nl;
|
||||
*ret = TAKE_PTR(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const NLTypeSystem *genl_family_get_type_system(const GenericNetlinkFamily *family) {
|
||||
assert(family);
|
||||
|
||||
if (family->type_system)
|
||||
return family->type_system;
|
||||
|
||||
return genl_get_type_system_by_name(family->name);
|
||||
}
|
||||
|
||||
static int genl_message_new(
|
||||
sd_netlink *nl,
|
||||
const GenericNetlinkFamily *family,
|
||||
uint8_t cmd,
|
||||
sd_netlink_message **ret) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(family);
|
||||
assert(ret);
|
||||
|
||||
type_system = genl_family_get_type_system(family);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = message_new_full(nl, family->id, type_system,
|
||||
sizeof(struct genlmsghdr) + family->additional_header_size, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*(struct genlmsghdr *) NLMSG_DATA(m->hdr) = (struct genlmsghdr) {
|
||||
.cmd = cmd,
|
||||
.version = family->version,
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genl_family_get_by_name_internal(
|
||||
sd_netlink *nl,
|
||||
const GenericNetlinkFamily *ctrl,
|
||||
const char *name,
|
||||
const GenericNetlinkFamily **ret) {
|
||||
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ctrl);
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
type_system = genl_get_type_system_by_name(name);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = genl_message_new(nl, ctrl, CTRL_CMD_GETFAMILY, &req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(req, CTRL_ATTR_FAMILY_NAME, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(nl, req, 0, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_family_new(nl, name, type_system, reply, ret);
|
||||
}
|
||||
|
||||
static int genl_family_get_by_name(sd_netlink *nl, const char *name, const GenericNetlinkFamily **ret) {
|
||||
const GenericNetlinkFamily *f, *ctrl;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(name);
|
||||
assert(ret);
|
||||
|
||||
f = hashmap_get(nl->genl_family_by_name, name);
|
||||
if (f) {
|
||||
if (f->id == 0) /* kernel does not support the family. */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (streq(name, CTRL_GENL_NAME))
|
||||
return genl_family_get_by_name_internal(nl, &nlctrl_static, CTRL_GENL_NAME, ret);
|
||||
|
||||
ctrl = hashmap_get(nl->genl_family_by_name, CTRL_GENL_NAME);
|
||||
if (!ctrl) {
|
||||
r = genl_family_get_by_name_internal(nl, &nlctrl_static, CTRL_GENL_NAME, &ctrl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return genl_family_get_by_name_internal(nl, ctrl, name, ret);
|
||||
}
|
||||
|
||||
static int genl_family_get_by_id(sd_netlink *nl, uint16_t id, const GenericNetlinkFamily **ret) {
|
||||
const GenericNetlinkFamily *f;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
assert(ret);
|
||||
|
||||
f = hashmap_get(nl->genl_family_by_id, UINT_TO_PTR(id));
|
||||
if (f) {
|
||||
*ret = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id == GENL_ID_CTRL) {
|
||||
*ret = &nlctrl_static;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int genl_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t id,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size) {
|
||||
|
||||
const GenericNetlinkFamily *f;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->protocol == NETLINK_GENERIC);
|
||||
|
||||
r = genl_family_get_by_id(nl, id, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ret_type_system) {
|
||||
const NLTypeSystem *t;
|
||||
|
||||
t = genl_family_get_type_system(f);
|
||||
if (!t)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
*ret_type_system = t;
|
||||
}
|
||||
if (ret_header_size)
|
||||
*ret_header_size = sizeof(struct genlmsghdr) + f->additional_header_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_new(sd_netlink *nl, const char *family_name, uint8_t cmd, sd_netlink_message **ret) {
|
||||
const GenericNetlinkFamily *family;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(family_name, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = genl_family_get_by_name(nl, family_name, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return genl_message_new(nl, family, cmd, ret);
|
||||
}
|
||||
|
||||
int sd_genl_message_get_family_name(sd_netlink *nl, sd_netlink_message *m, const char **ret) {
|
||||
const GenericNetlinkFamily *family;
|
||||
uint16_t nlmsg_type;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_family_get_by_id(nl, nlmsg_type, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = family->name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_message_get_command(sd_netlink *nl, sd_netlink_message *m, uint8_t *ret) {
|
||||
struct genlmsghdr *h;
|
||||
uint16_t nlmsg_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = sd_netlink_message_get_type(m, &nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_get_type_system_and_header_size(nl, nlmsg_type, NULL, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (m->hdr->nlmsg_len < NLMSG_LENGTH(size))
|
||||
return -EBADMSG;
|
||||
|
||||
h = NLMSG_DATA(m->hdr);
|
||||
|
||||
*ret = h->cmd;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int genl_family_get_multicast_group_id_by_name(const GenericNetlinkFamily *f, const char *name, uint32_t *ret) {
|
||||
void *p;
|
||||
|
||||
assert(f);
|
||||
assert(name);
|
||||
|
||||
p = hashmap_get(f->multicast_group_by_name, name);
|
||||
if (!p)
|
||||
return -ENOENT;
|
||||
|
||||
if (ret)
|
||||
*ret = PTR_TO_UINT32(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_genl_add_match(
|
||||
sd_netlink *nl,
|
||||
sd_netlink_slot **ret_slot,
|
||||
const char *family_name,
|
||||
const char *multicast_group_name,
|
||||
uint8_t command,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata,
|
||||
const char *description) {
|
||||
|
||||
const GenericNetlinkFamily *f;
|
||||
uint32_t multicast_group_id;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL);
|
||||
assert_return(callback, -EINVAL);
|
||||
assert_return(family_name, -EINVAL);
|
||||
assert_return(multicast_group_name, -EINVAL);
|
||||
|
||||
/* If command == 0, then all commands belonging to the multicast group trigger the callback. */
|
||||
|
||||
r = genl_family_get_by_name(nl, family_name, &f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = genl_family_get_multicast_group_id_by_name(f, multicast_group_name, &multicast_group_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return netlink_add_match_internal(nl, ret_slot, &multicast_group_id, 1, f->id, command,
|
||||
callback, destroy_callback, userdata, description);
|
||||
}
|
||||
|
||||
int sd_genl_socket_open(sd_netlink **ret) {
|
||||
return netlink_open_family(ret, NETLINK_GENERIC);
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#define CTRL_GENL_NAME "nlctrl"
|
||||
|
||||
void genl_clear_family(sd_netlink *nl);
|
||||
@ -10,11 +10,11 @@
|
||||
#include "prioq.h"
|
||||
#include "time-util.h"
|
||||
|
||||
#define NETLINK_DEFAULT_TIMEOUT_USEC ((usec_t) (25 * USEC_PER_SEC))
|
||||
#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
|
||||
|
||||
#define NETLINK_RQUEUE_MAX 64*1024
|
||||
#define RTNL_RQUEUE_MAX 64*1024
|
||||
|
||||
#define NETLINK_CONTAINER_DEPTH 32
|
||||
#define RTNL_CONTAINER_DEPTH 32
|
||||
|
||||
struct reply_callback {
|
||||
sd_netlink_message_handler_t callback;
|
||||
@ -25,10 +25,7 @@ struct reply_callback {
|
||||
|
||||
struct match_callback {
|
||||
sd_netlink_message_handler_t callback;
|
||||
uint32_t *groups;
|
||||
size_t n_groups;
|
||||
uint16_t type;
|
||||
uint8_t cmd; /* used by genl */
|
||||
|
||||
LIST_FIELDS(struct match_callback, match_callbacks);
|
||||
};
|
||||
@ -98,8 +95,8 @@ struct sd_netlink {
|
||||
sd_event_source *exit_event_source;
|
||||
sd_event *event;
|
||||
|
||||
Hashmap *genl_family_by_name;
|
||||
Hashmap *genl_family_by_id;
|
||||
Hashmap *genl_family_to_nlmsg_type;
|
||||
Hashmap *nlmsg_type_to_genl_family;
|
||||
};
|
||||
|
||||
struct netlink_attribute {
|
||||
@ -121,7 +118,7 @@ struct sd_netlink_message {
|
||||
int protocol;
|
||||
|
||||
struct nlmsghdr *hdr;
|
||||
struct netlink_container containers[NETLINK_CONTAINER_DEPTH];
|
||||
struct netlink_container containers[RTNL_CONTAINER_DEPTH];
|
||||
unsigned n_containers; /* number of containers */
|
||||
bool sealed:1;
|
||||
bool broadcast:1;
|
||||
@ -129,22 +126,10 @@ struct sd_netlink_message {
|
||||
sd_netlink_message *next; /* next in a chain of multi-part messages */
|
||||
};
|
||||
|
||||
int message_new_empty(sd_netlink *nl, sd_netlink_message **ret);
|
||||
int message_new_full(
|
||||
sd_netlink *nl,
|
||||
uint16_t nlmsg_type,
|
||||
const NLTypeSystem *type_system,
|
||||
size_t header_size,
|
||||
sd_netlink_message **ret);
|
||||
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type);
|
||||
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret);
|
||||
uint32_t message_get_serial(sd_netlink_message *m);
|
||||
void message_seal(sd_netlink_message *m);
|
||||
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type);
|
||||
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret);
|
||||
|
||||
int netlink_open_family(sd_netlink **ret, int family);
|
||||
bool netlink_pid_changed(sd_netlink *nl);
|
||||
int netlink_rqueue_make_room(sd_netlink *nl);
|
||||
int netlink_rqueue_partial_make_room(sd_netlink *nl);
|
||||
|
||||
int socket_open(int family);
|
||||
int socket_bind(sd_netlink *nl);
|
||||
@ -154,18 +139,9 @@ int socket_write_message(sd_netlink *nl, sd_netlink_message *m);
|
||||
int socket_writev_message(sd_netlink *nl, sd_netlink_message **m, size_t msgcount);
|
||||
int socket_read_message(sd_netlink *nl);
|
||||
|
||||
int netlink_add_match_internal(
|
||||
sd_netlink *nl,
|
||||
sd_netlink_slot **ret_slot,
|
||||
const uint32_t *groups,
|
||||
size_t n_groups,
|
||||
uint16_t type,
|
||||
uint8_t cmd,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata,
|
||||
const char *description);
|
||||
int rtnl_rqueue_make_room(sd_netlink *rtnl);
|
||||
int rtnl_rqueue_partial_make_room(sd_netlink *rtnl);
|
||||
|
||||
/* Make sure callbacks don't destroy the netlink connection */
|
||||
#define NETLINK_DONT_DESTROY(nl) \
|
||||
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##nl = sd_netlink_ref(nl)
|
||||
/* Make sure callbacks don't destroy the rtnl connection */
|
||||
#define NETLINK_DONT_DESTROY(rtnl) \
|
||||
_cleanup_(sd_netlink_unrefp) _unused_ sd_netlink *_dont_destroy_##rtnl = sd_netlink_ref(rtnl)
|
||||
|
||||
@ -20,14 +20,15 @@
|
||||
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
|
||||
#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
|
||||
|
||||
int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
|
||||
int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
|
||||
sd_netlink_message *m;
|
||||
|
||||
assert(nl);
|
||||
assert(ret);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
/* Note that 'nl' is currently unused, if we start using it internally we must take care to
|
||||
* avoid problems due to mutual references between buses and their queued messages. See sd-bus. */
|
||||
/* Note that 'rtnl' is currently unused, if we start using it internally
|
||||
we must take care to avoid problems due to mutual references between
|
||||
buses and their queued messages. See sd-bus.
|
||||
*/
|
||||
|
||||
m = new(sd_netlink_message, 1);
|
||||
if (!m)
|
||||
@ -35,80 +36,48 @@ int message_new_empty(sd_netlink *nl, sd_netlink_message **ret) {
|
||||
|
||||
*m = (sd_netlink_message) {
|
||||
.n_ref = 1,
|
||||
.protocol = nl->protocol,
|
||||
.protocol = rtnl->protocol,
|
||||
.sealed = false,
|
||||
};
|
||||
|
||||
*ret = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int message_new_full(
|
||||
sd_netlink *nl,
|
||||
uint16_t nlmsg_type,
|
||||
const NLTypeSystem *type_system,
|
||||
size_t header_size,
|
||||
sd_netlink_message **ret) {
|
||||
|
||||
int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *nl_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(type_system);
|
||||
assert(ret);
|
||||
assert_return(rtnl, -EINVAL);
|
||||
|
||||
size = NLMSG_SPACE(header_size);
|
||||
assert(size >= sizeof(struct nlmsghdr));
|
||||
|
||||
r = message_new_empty(nl, &m);
|
||||
r = type_system_root_get_type(rtnl, &nl_type, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->containers[0].type_system = type_system;
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = message_new_empty(rtnl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(type_get_size(nl_type));
|
||||
|
||||
assert(size >= sizeof(struct nlmsghdr));
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = nlmsg_type;
|
||||
m->hdr->nlmsg_type = type;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int message_new(sd_netlink *nl, sd_netlink_message **ret, uint16_t type) {
|
||||
const NLTypeSystem *type_system;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = type_system_root_get_type_system_and_header_size(nl, type, &type_system, &size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return message_new_full(nl, type, type_system, size, ret);
|
||||
}
|
||||
|
||||
int message_new_synthetic_error(sd_netlink *nl, int error, uint32_t serial, sd_netlink_message **ret) {
|
||||
struct nlmsgerr *err;
|
||||
int r;
|
||||
|
||||
assert(error <= 0);
|
||||
|
||||
r = message_new(nl, ret, NLMSG_ERROR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
message_seal(*ret);
|
||||
(*ret)->hdr->nlmsg_seq = serial;
|
||||
|
||||
err = NLMSG_DATA((*ret)->hdr);
|
||||
err->error = error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -215,12 +184,13 @@ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *da
|
||||
|
||||
static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) {
|
||||
const NLType *type;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
type = type_system_get_type(m->containers[m->n_containers].type_system, attribute_type);
|
||||
if (!type)
|
||||
return -EOPNOTSUPP;
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(type) != data_type)
|
||||
return -EINVAL;
|
||||
@ -568,7 +538,7 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
/* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
|
||||
if (r < 0) {
|
||||
@ -583,23 +553,22 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_union_get_type_system_by_protocol(
|
||||
type_system_union,
|
||||
r = type_system_union_protocol_get_type_system(type_system_union,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
family);
|
||||
} else
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
type);
|
||||
if (!m->containers[m->n_containers + 1].type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
|
||||
if (r < 0)
|
||||
@ -616,22 +585,19 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
type);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->containers[m->n_containers + 1].type_system =
|
||||
type_system_union_get_type_system_by_string(
|
||||
type_system_union,
|
||||
r = type_system_union_get_type_system(type_system_union,
|
||||
&m->containers[m->n_containers + 1].type_system,
|
||||
key);
|
||||
if (!m->containers[m->n_containers + 1].type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_string(m, type_system_union_get_match_attribute(type_system_union), key);
|
||||
r = sd_netlink_message_append_string(m, type_system_union->match, key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -662,7 +628,7 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
|
||||
if (r < 0)
|
||||
@ -707,7 +673,7 @@ static int netlink_message_read_internal(
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->sealed, -EPERM);
|
||||
|
||||
assert(m->n_containers < NETLINK_CONTAINER_DEPTH);
|
||||
assert(m->n_containers < RTNL_CONTAINER_DEPTH);
|
||||
|
||||
if (!m->containers[m->n_containers].attributes)
|
||||
return -ENODATA;
|
||||
@ -1042,26 +1008,26 @@ int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < NETLINK_CONTAINER_DEPTH, -EINVAL);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
|
||||
|
||||
nl_type = type_system_get_type(
|
||||
m->containers[m->n_containers].type_system,
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
container_type);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
type_system = type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&type_system,
|
||||
container_type);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nl_type = type_system_get_type(type_system, type_id);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
r = type_system_get_type(type_system, &nl_type, type_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_STRING)
|
||||
return -EINVAL;
|
||||
@ -1113,7 +1079,7 @@ static int netlink_container_parse(sd_netlink_message *m,
|
||||
return -ENOMEM;
|
||||
|
||||
if (attributes[type].offset != 0)
|
||||
log_debug("sd-netlink: message parse - overwriting repeated attribute");
|
||||
log_debug("rtnl: message parse - overwriting repeated attribute");
|
||||
|
||||
attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
|
||||
attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
|
||||
@ -1138,62 +1104,61 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
nl_type = type_system_get_type(
|
||||
m->containers[m->n_containers].type_system,
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
type_id);
|
||||
if (!nl_type)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type = type_get_type(nl_type);
|
||||
|
||||
if (type == NETLINK_TYPE_NESTED) {
|
||||
type_system = type_system_get_type_system(
|
||||
m->containers[m->n_containers].type_system,
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&type_system,
|
||||
type_id);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (type == NETLINK_TYPE_UNION) {
|
||||
const NLTypeSystemUnion *type_system_union;
|
||||
|
||||
type_system_union = type_system_get_type_system_union(
|
||||
m->containers[m->n_containers].type_system,
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system,
|
||||
&type_system_union,
|
||||
type_id);
|
||||
if (!type_system_union)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (type_system_union_get_match_type(type_system_union)) {
|
||||
case NL_MATCH_SIBLING: {
|
||||
const char *key;
|
||||
|
||||
r = sd_netlink_message_read_string(
|
||||
m,
|
||||
type_system_union_get_match_attribute(type_system_union),
|
||||
&key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type_system = type_system_union_get_type_system_by_string(
|
||||
type_system_union,
|
||||
switch (type_system_union->match_type) {
|
||||
case NL_MATCH_SIBLING:
|
||||
{
|
||||
const char *key;
|
||||
|
||||
r = sd_netlink_message_read_string(m, type_system_union->match, &key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = type_system_union_get_type_system(type_system_union,
|
||||
&type_system,
|
||||
key);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
case NL_MATCH_PROTOCOL: {
|
||||
case NL_MATCH_PROTOCOL:
|
||||
{
|
||||
int family;
|
||||
|
||||
r = sd_rtnl_message_get_family(m, &family);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
type_system = type_system_union_get_type_system_by_protocol(
|
||||
type_system_union,
|
||||
r = type_system_union_protocol_get_type_system(type_system_union,
|
||||
&type_system,
|
||||
family);
|
||||
if (!type_system)
|
||||
return -EOPNOTSUPP;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
break;
|
||||
}
|
||||
@ -1230,7 +1195,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < (NETLINK_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
r = netlink_message_read_internal(m, type_id, &container, NULL);
|
||||
if (r < 0)
|
||||
@ -1266,7 +1231,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t message_get_serial(sd_netlink_message *m) {
|
||||
uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
|
||||
assert(m);
|
||||
assert(m->hdr);
|
||||
|
||||
@ -1315,15 +1280,18 @@ static int netlink_message_parse_error(sd_netlink_message *m) {
|
||||
NLMSG_PAYLOAD(m->hdr, hlen));
|
||||
}
|
||||
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
|
||||
const NLType *nl_type;
|
||||
uint16_t type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(nl, -EINVAL);
|
||||
assert_return(genl || m->protocol != NETLINK_GENERIC, -EINVAL);
|
||||
|
||||
/* don't allow appending to message once parsed */
|
||||
message_seal(m);
|
||||
if (!m->sealed)
|
||||
rtnl_message_seal(m);
|
||||
|
||||
for (unsigned i = 1; i <= m->n_containers; i++)
|
||||
m->containers[i].attributes = mfree(m->containers[i].attributes);
|
||||
@ -1336,22 +1304,37 @@ int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl) {
|
||||
|
||||
assert(m->hdr);
|
||||
|
||||
r = type_system_root_get_type_system_and_header_size(nl, m->hdr->nlmsg_type,
|
||||
&m->containers[0].type_system, &size);
|
||||
r = type_system_root_get_type(genl, &nl_type, m->hdr->nlmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_netlink_message_is_error(m))
|
||||
return netlink_message_parse_error(m);
|
||||
type = type_get_type(nl_type);
|
||||
size = type_get_size(nl_type);
|
||||
|
||||
return netlink_container_parse(m,
|
||||
&m->containers[0],
|
||||
if (type == NETLINK_TYPE_NESTED) {
|
||||
const NLTypeSystem *type_system;
|
||||
|
||||
type_get_type_system(nl_type, &type_system);
|
||||
|
||||
m->containers[0].type_system = type_system;
|
||||
|
||||
if (sd_netlink_message_is_error(m))
|
||||
r = netlink_message_parse_error(m);
|
||||
else
|
||||
r = netlink_container_parse(m,
|
||||
&m->containers[m->n_containers],
|
||||
(struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
|
||||
NLMSG_PAYLOAD(m->hdr, size));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void message_seal(sd_netlink_message *m) {
|
||||
void rtnl_message_seal(sd_netlink_message *m) {
|
||||
assert(m);
|
||||
assert(!m->sealed);
|
||||
|
||||
m->sealed = true;
|
||||
}
|
||||
|
||||
@ -70,11 +70,25 @@ void netlink_slot_disconnect(sd_netlink_slot *slot, bool unref) {
|
||||
case NETLINK_MATCH_CALLBACK:
|
||||
LIST_REMOVE(match_callbacks, nl->match_callbacks, &slot->match_callback);
|
||||
|
||||
for (size_t i = 0; i < slot->match_callback.n_groups; i++)
|
||||
(void) socket_broadcast_group_unref(nl, slot->match_callback.groups[i]);
|
||||
switch (slot->match_callback.type) {
|
||||
case RTM_NEWLINK:
|
||||
case RTM_DELLINK:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_LINK);
|
||||
|
||||
slot->match_callback.n_groups = 0;
|
||||
slot->match_callback.groups = mfree(slot->match_callback.groups);
|
||||
break;
|
||||
case RTM_NEWADDR:
|
||||
case RTM_DELADDR:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_IFADDR);
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_IFADDR);
|
||||
|
||||
break;
|
||||
case RTM_NEWROUTE:
|
||||
case RTM_DELROUTE:
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV4_ROUTE);
|
||||
(void) socket_broadcast_group_unref(nl, RTNLGRP_IPV6_ROUTE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
@ -238,7 +238,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
|
||||
n = recvmsg_safe(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
|
||||
if (n == -ENOBUFS)
|
||||
return log_debug_errno(n, "sd-netlink: kernel receive buffer overrun");
|
||||
return log_debug_errno(n, "rtnl: kernel receive buffer overrun");
|
||||
if (IN_SET(n, -EAGAIN, -EINTR))
|
||||
return 0;
|
||||
if (n < 0)
|
||||
@ -246,7 +246,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
|
||||
if (sender.nl.nl_pid != 0) {
|
||||
/* not from the kernel, ignore */
|
||||
log_debug("sd-netlink: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
|
||||
log_debug("rtnl: ignoring message from PID %"PRIu32, sender.nl.nl_pid);
|
||||
|
||||
if (peek) {
|
||||
/* drop the message */
|
||||
@ -276,7 +276,7 @@ static int socket_recv_message(int fd, struct iovec *iov, uint32_t *ret_mcast_gr
|
||||
* If nothing useful was received 0 is returned.
|
||||
* On failure, a negative error code is returned.
|
||||
*/
|
||||
int socket_read_message(sd_netlink *nl) {
|
||||
int socket_read_message(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *first = NULL;
|
||||
bool multi_part = false, done = false;
|
||||
size_t len, allocated;
|
||||
@ -285,25 +285,25 @@ int socket_read_message(sd_netlink *nl) {
|
||||
unsigned i = 0;
|
||||
int r;
|
||||
|
||||
assert(nl);
|
||||
assert(nl->rbuffer);
|
||||
assert(rtnl);
|
||||
assert(rtnl->rbuffer);
|
||||
|
||||
/* read nothing, just get the pending message size */
|
||||
r = socket_recv_message(nl->fd, &iov, NULL, true);
|
||||
r = socket_recv_message(rtnl->fd, &iov, NULL, true);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
else
|
||||
len = (size_t) r;
|
||||
|
||||
/* make room for the pending message */
|
||||
if (!greedy_realloc((void**) &nl->rbuffer, len, sizeof(uint8_t)))
|
||||
if (!greedy_realloc((void **)&rtnl->rbuffer, len, sizeof(uint8_t)))
|
||||
return -ENOMEM;
|
||||
|
||||
allocated = MALLOC_SIZEOF_SAFE(nl->rbuffer);
|
||||
iov = IOVEC_MAKE(nl->rbuffer, allocated);
|
||||
allocated = MALLOC_SIZEOF_SAFE(rtnl->rbuffer);
|
||||
iov = IOVEC_MAKE(rtnl->rbuffer, allocated);
|
||||
|
||||
/* read the pending message */
|
||||
r = socket_recv_message(nl->fd, &iov, &group, false);
|
||||
r = socket_recv_message(rtnl->fd, &iov, &group, false);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
else
|
||||
@ -313,22 +313,22 @@ int socket_read_message(sd_netlink *nl) {
|
||||
/* message did not fit in read buffer */
|
||||
return -EIO;
|
||||
|
||||
if (NLMSG_OK(nl->rbuffer, len) && nl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
|
||||
if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
|
||||
multi_part = true;
|
||||
|
||||
for (i = 0; i < nl->rqueue_partial_size; i++)
|
||||
if (message_get_serial(nl->rqueue_partial[i]) ==
|
||||
nl->rbuffer->nlmsg_seq) {
|
||||
first = nl->rqueue_partial[i];
|
||||
for (i = 0; i < rtnl->rqueue_partial_size; i++)
|
||||
if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
|
||||
rtnl->rbuffer->nlmsg_seq) {
|
||||
first = rtnl->rqueue_partial[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (struct nlmsghdr *new_msg = nl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
||||
for (struct nlmsghdr *new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len) && !done; new_msg = NLMSG_NEXT(new_msg, len)) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
size_t size;
|
||||
const NLType *nl_type;
|
||||
|
||||
if (!group && new_msg->nlmsg_pid != nl->sockaddr.nl.nl_pid)
|
||||
if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
|
||||
/* not broadcast and not for us */
|
||||
continue;
|
||||
|
||||
@ -346,7 +346,7 @@ int socket_read_message(sd_netlink *nl) {
|
||||
}
|
||||
|
||||
/* check that we support this message type */
|
||||
r = type_system_root_get_type_system_and_header_size(nl, new_msg->nlmsg_type, NULL, &size);
|
||||
r = type_system_root_get_type(rtnl, &nl_type, new_msg->nlmsg_type);
|
||||
if (r < 0) {
|
||||
if (r == -EOPNOTSUPP)
|
||||
log_debug("sd-netlink: ignored message with unknown type: %i",
|
||||
@ -356,12 +356,12 @@ int socket_read_message(sd_netlink *nl) {
|
||||
}
|
||||
|
||||
/* check that the size matches the message type */
|
||||
if (new_msg->nlmsg_len < NLMSG_LENGTH(size)) {
|
||||
if (new_msg->nlmsg_len < NLMSG_LENGTH(type_get_size(nl_type))) {
|
||||
log_debug("sd-netlink: message is shorter than expected, dropping");
|
||||
continue;
|
||||
}
|
||||
|
||||
r = message_new_empty(nl, &m);
|
||||
r = message_new_empty(rtnl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -372,7 +372,7 @@ int socket_read_message(sd_netlink *nl) {
|
||||
return -ENOMEM;
|
||||
|
||||
/* seal and parse the top-level message */
|
||||
r = sd_netlink_message_rewind(m, nl);
|
||||
r = sd_netlink_message_rewind(m, rtnl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -390,31 +390,31 @@ int socket_read_message(sd_netlink *nl) {
|
||||
|
||||
if (!multi_part || done) {
|
||||
/* we got a complete message, push it on the read queue */
|
||||
r = netlink_rqueue_make_room(nl);
|
||||
r = rtnl_rqueue_make_room(rtnl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nl->rqueue[nl->rqueue_size++] = TAKE_PTR(first);
|
||||
rtnl->rqueue[rtnl->rqueue_size++] = TAKE_PTR(first);
|
||||
|
||||
if (multi_part && (i < nl->rqueue_partial_size)) {
|
||||
if (multi_part && (i < rtnl->rqueue_partial_size)) {
|
||||
/* remove the message form the partial read queue */
|
||||
memmove(nl->rqueue_partial + i, nl->rqueue_partial + i + 1,
|
||||
sizeof(sd_netlink_message*) * (nl->rqueue_partial_size - i - 1));
|
||||
nl->rqueue_partial_size--;
|
||||
memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
|
||||
sizeof(sd_netlink_message*) * (rtnl->rqueue_partial_size - i - 1));
|
||||
rtnl->rqueue_partial_size--;
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
/* we only got a partial multi-part message, push it on the
|
||||
partial read queue */
|
||||
if (i < nl->rqueue_partial_size)
|
||||
nl->rqueue_partial[i] = TAKE_PTR(first);
|
||||
if (i < rtnl->rqueue_partial_size)
|
||||
rtnl->rqueue_partial[i] = TAKE_PTR(first);
|
||||
else {
|
||||
r = netlink_rqueue_partial_make_room(nl);
|
||||
r = rtnl_rqueue_partial_make_room(rtnl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nl->rqueue_partial[nl->rqueue_partial_size++] = TAKE_PTR(first);
|
||||
rtnl->rqueue_partial[rtnl->rqueue_partial_size++] = TAKE_PTR(first);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1,234 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/batman_adv.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/wireguard.h>
|
||||
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-types-internal.h"
|
||||
|
||||
/***************** genl ctrl type systems *****************/
|
||||
static const NLType genl_ctrl_mcast_group_types[] = {
|
||||
[CTRL_ATTR_MCAST_GRP_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[CTRL_ATTR_MCAST_GRP_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_ctrl_mcast_group);
|
||||
|
||||
static const NLType genl_ctrl_ops_types[] = {
|
||||
[CTRL_ATTR_OP_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_OP_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_ctrl_ops);
|
||||
|
||||
static const NLType genl_ctrl_types[] = {
|
||||
[CTRL_ATTR_FAMILY_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[CTRL_ATTR_FAMILY_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[CTRL_ATTR_VERSION] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_HDRSIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_MAXATTR] = { .type = NETLINK_TYPE_U32 },
|
||||
[CTRL_ATTR_OPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_ops_type_system },
|
||||
[CTRL_ATTR_MCAST_GROUPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_ctrl_mcast_group_type_system },
|
||||
/*
|
||||
[CTRL_ATTR_POLICY] = { .type = NETLINK_TYPE_NESTED, },
|
||||
[CTRL_ATTR_OP_POLICY] = { .type = NETLINK_TYPE_NESTED, }
|
||||
*/
|
||||
[CTRL_ATTR_OP] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl batadv type systems *****************/
|
||||
static const NLType genl_batadv_types[] = {
|
||||
[BATADV_ATTR_VERSION] = { .type = NETLINK_TYPE_STRING },
|
||||
[BATADV_ATTR_ALGO_NAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[BATADV_ATTR_MESH_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MESH_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
|
||||
[BATADV_ATTR_MESH_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_HARD_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_HARD_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ },
|
||||
[BATADV_ATTR_HARD_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_ORIG_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TPMETER_RESULT] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_TPMETER_BYTES] = { .type = NETLINK_TYPE_U64 },
|
||||
[BATADV_ATTR_TPMETER_COOKIE] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_PAD] = { .type = NETLINK_TYPE_UNSPEC },
|
||||
[BATADV_ATTR_ACTIVE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_TT_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TT_TTVN] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TT_LAST_TTVN] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_TT_CRC32] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_TT_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_TT_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_FLAG_BEST] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_NEIGH_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_TQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_THROUGHPUT] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BANDWIDTH_UP] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ROUTER] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_OWN] = { .type = NETLINK_TYPE_FLAG },
|
||||
[BATADV_ATTR_BLA_ADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_BLA_BACKBONE] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_BLA_CRC] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_DAT_CACHE_IP4ADDRESS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_DAT_CACHE_HWADDRESS] = { .size = ETH_ALEN },
|
||||
[BATADV_ATTR_DAT_CACHE_VID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_MCAST_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MCAST_FLAGS_PRIV] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_VLANID] = { .type = NETLINK_TYPE_U16 },
|
||||
[BATADV_ATTR_AGGREGATED_OGMS_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_AP_ISOLATION_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_ISOLATION_MARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ISOLATION_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_BONDING_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_FRAGMENTATION_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_GW_BANDWIDTH_DOWN] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_GW_BANDWIDTH_UP] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_GW_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_GW_SEL_CLASS] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_HOP_PENALTY] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_LOG_LEVEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_MULTICAST_FANOUT] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_NETWORK_CODING_ENABLED] = { .type = NETLINK_TYPE_U8 },
|
||||
[BATADV_ATTR_ORIG_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_ELP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl fou type systems *****************/
|
||||
static const NLType genl_fou_types[] = {
|
||||
[FOU_ATTR_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[FOU_ATTR_AF] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_IPPROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_TYPE] = { .type = NETLINK_TYPE_U8 },
|
||||
[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
|
||||
[FOU_ATTR_LOCAL_V4] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_PEER_V4] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_LOCAL_V6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FOU_ATTR_PEER_V6] = { .type = NETLINK_TYPE_IN_ADDR},
|
||||
[FOU_ATTR_PEER_PORT] = { .type = NETLINK_TYPE_U16},
|
||||
[FOU_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32},
|
||||
};
|
||||
|
||||
/***************** genl l2tp type systems *****************/
|
||||
static const NLType genl_l2tp_types[] = {
|
||||
[L2TP_ATTR_PW_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_OFFSET] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_DATA_SEQ] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_L2SPEC_TYPE] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_L2SPEC_LEN] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_PROTO_VERSION] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_IFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[L2TP_ATTR_CONN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_PEER_CONN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_SESSION_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_PEER_SESSION_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_RECV_SEQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_SEND_SEQ] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_LNS_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_USING_IPSEC] = { .type = NETLINK_TYPE_U8 },
|
||||
[L2TP_ATTR_FD] = { .type = NETLINK_TYPE_U32 },
|
||||
[L2TP_ATTR_IP_SADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_IP_DADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_UDP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_UDP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[L2TP_ATTR_IP6_SADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_IP6_DADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[L2TP_ATTR_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_FLAG },
|
||||
[L2TP_ATTR_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
/***************** genl macsec type systems *****************/
|
||||
static const NLType genl_macsec_rxsc_types[] = {
|
||||
[MACSEC_RXSC_ATTR_SCI] = { .type = NETLINK_TYPE_U64 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_macsec_rxsc);
|
||||
|
||||
static const NLType genl_macsec_sa_types[] = {
|
||||
[MACSEC_SA_ATTR_AN] = { .type = NETLINK_TYPE_U8 },
|
||||
[MACSEC_SA_ATTR_ACTIVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[MACSEC_SA_ATTR_PN] = { .type = NETLINK_TYPE_U32 },
|
||||
[MACSEC_SA_ATTR_KEYID] = { .size = MACSEC_KEYID_LEN },
|
||||
[MACSEC_SA_ATTR_KEY] = { .size = MACSEC_MAX_KEY_LEN },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_macsec_sa);
|
||||
|
||||
static const NLType genl_macsec_types[] = {
|
||||
[MACSEC_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[MACSEC_ATTR_RXSC_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_rxsc_type_system },
|
||||
[MACSEC_ATTR_SA_CONFIG] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_macsec_sa_type_system },
|
||||
};
|
||||
|
||||
/***************** genl nl80211 type systems *****************/
|
||||
static const NLType genl_nl80211_types[] = {
|
||||
[NL80211_ATTR_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NL80211_ATTR_MAC] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[NL80211_ATTR_SSID] = { .type = NETLINK_TYPE_STRING },
|
||||
[NL80211_ATTR_IFTYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
/***************** genl wireguard type systems *****************/
|
||||
static const NLType genl_wireguard_allowedip_types[] = {
|
||||
[WGALLOWEDIP_A_FAMILY] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGALLOWEDIP_A_IPADDR] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[WGALLOWEDIP_A_CIDR_MASK] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_wireguard_allowedip);
|
||||
|
||||
static const NLType genl_wireguard_peer_types[] = {
|
||||
[WGPEER_A_PUBLIC_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGPEER_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGPEER_A_PRESHARED_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGPEER_A_ENDPOINT] = { .type = NETLINK_TYPE_SOCKADDR },
|
||||
[WGPEER_A_ALLOWEDIPS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_allowedip_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(genl_wireguard_peer);
|
||||
|
||||
static const NLType genl_wireguard_types[] = {
|
||||
[WGDEVICE_A_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ-1 },
|
||||
[WGDEVICE_A_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_PRIVATE_KEY] = { .size = WG_KEY_LEN },
|
||||
[WGDEVICE_A_LISTEN_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[WGDEVICE_A_FWMARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[WGDEVICE_A_PEERS] = { .type = NETLINK_TYPE_NESTED, .type_system = &genl_wireguard_peer_type_system },
|
||||
};
|
||||
|
||||
/***************** genl families *****************/
|
||||
static const NLTypeSystemUnionElement genl_type_systems[] = {
|
||||
{ .name = CTRL_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_ctrl), },
|
||||
{ .name = BATADV_NL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_batadv), },
|
||||
{ .name = FOU_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_fou), },
|
||||
{ .name = L2TP_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_l2tp), },
|
||||
{ .name = MACSEC_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_macsec), },
|
||||
{ .name = NL80211_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_nl80211), },
|
||||
{ .name = WG_GENL_NAME, .type_system = TYPE_SYSTEM_FROM_TYPE(genl_wireguard), },
|
||||
};
|
||||
|
||||
/* This is the root type system union, so match_attribute is not necessary. */
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(genl, 0);
|
||||
|
||||
const NLTypeSystem *genl_get_type_system_by_name(const char *name) {
|
||||
return type_system_union_get_type_system_by_string(&genl_type_system_union, name);
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "macro.h"
|
||||
#include "netlink-types.h"
|
||||
|
||||
struct NLType {
|
||||
uint16_t type;
|
||||
size_t size;
|
||||
const NLTypeSystem *type_system;
|
||||
const NLTypeSystemUnion *type_system_union;
|
||||
};
|
||||
|
||||
struct NLTypeSystem {
|
||||
uint16_t count;
|
||||
const NLType *types;
|
||||
};
|
||||
|
||||
typedef struct NLTypeSystemUnionElement {
|
||||
union {
|
||||
int protocol;
|
||||
const char *name;
|
||||
};
|
||||
NLTypeSystem type_system;
|
||||
} NLTypeSystemUnionElement;
|
||||
|
||||
struct NLTypeSystemUnion {
|
||||
size_t count;
|
||||
const NLTypeSystemUnionElement *elements;
|
||||
NLMatchType match_type;
|
||||
uint16_t match_attribute;
|
||||
};
|
||||
|
||||
#define TYPE_SYSTEM_FROM_TYPE(name) \
|
||||
{ .count = ELEMENTSOF(name##_types), .types = name##_types }
|
||||
#define DEFINE_TYPE_SYSTEM(name) \
|
||||
static const NLTypeSystem name##_type_system = TYPE_SYSTEM_FROM_TYPE(name)
|
||||
|
||||
#define _DEFINE_TYPE_SYSTEM_UNION(name, type, attr) \
|
||||
static const NLTypeSystemUnion name##_type_system_union = { \
|
||||
.count = ELEMENTSOF(name##_type_systems), \
|
||||
.elements = name##_type_systems, \
|
||||
.match_type = type, \
|
||||
.match_attribute = attr, \
|
||||
}
|
||||
#define DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(name) \
|
||||
_DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_PROTOCOL, 0)
|
||||
#define DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(name, attr) \
|
||||
_DEFINE_TYPE_SYSTEM_UNION(name, NL_MATCH_SIBLING, attr)
|
||||
@ -1,197 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
|
||||
#include "netlink-types-internal.h"
|
||||
#include "string-table.h"
|
||||
|
||||
static const NLType nfnl_nft_table_types[] = {
|
||||
[NFTA_TABLE_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_TABLE_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_table);
|
||||
|
||||
static const NLType nfnl_nft_chain_hook_types[] = {
|
||||
[NFTA_HOOK_HOOKNUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_HOOK_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_HOOK_DEV] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_chain_hook);
|
||||
|
||||
static const NLType nfnl_nft_chain_types[] = {
|
||||
[NFTA_CHAIN_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_CHAIN_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_CHAIN_HOOK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_hook_type_system },
|
||||
[NFTA_CHAIN_TYPE] = { .type = NETLINK_TYPE_STRING, .size = 16 },
|
||||
[NFTA_CHAIN_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_chain);
|
||||
|
||||
static const NLType nfnl_nft_expr_meta_types[] = {
|
||||
[NFTA_META_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_META_KEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_META_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_payload_types[] = {
|
||||
[NFTA_PAYLOAD_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_BASE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_OFFSET] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_PAYLOAD_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_nat_types[] = {
|
||||
[NFTA_NAT_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_FAMILY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_ADDR_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_ADDR_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_NAT_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_data_types[] = {
|
||||
[NFTA_DATA_VALUE] = { .type = NETLINK_TYPE_BINARY },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_data);
|
||||
|
||||
static const NLType nfnl_nft_expr_bitwise_types[] = {
|
||||
[NFTA_BITWISE_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_BITWISE_MASK] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_BITWISE_XOR] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_cmp_types[] = {
|
||||
[NFTA_CMP_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_CMP_OP] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_CMP_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_fib_types[] = {
|
||||
[NFTA_FIB_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_FIB_RESULT] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_FIB_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_lookup_types[] = {
|
||||
[NFTA_LOOKUP_SET] = { .type = NETLINK_TYPE_STRING },
|
||||
[NFTA_LOOKUP_SREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_LOOKUP_DREG] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_LOOKUP_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType nfnl_nft_expr_masq_types[] = {
|
||||
[NFTA_MASQ_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_MASQ_REG_PROTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_MASQ_REG_PROTO_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement nfnl_expr_data_type_systems[] = {
|
||||
{ .name = "bitwise", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_bitwise), },
|
||||
{ .name = "cmp", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_cmp), },
|
||||
{ .name = "fib", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_fib), },
|
||||
{ .name = "lookup", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_lookup), },
|
||||
{ .name = "masq", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_masq), },
|
||||
{ .name = "meta", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_meta), },
|
||||
{ .name = "nat", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_nat), },
|
||||
{ .name = "payload", .type_system = TYPE_SYSTEM_FROM_TYPE(nfnl_nft_expr_payload), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(nfnl_expr_data, NFTA_EXPR_NAME);
|
||||
|
||||
static const NLType nfnl_nft_rule_expr_types[] = {
|
||||
[NFTA_EXPR_NAME] = { .type = NETLINK_TYPE_STRING, .size = 16 },
|
||||
[NFTA_EXPR_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &nfnl_expr_data_type_system_union },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_rule_expr);
|
||||
|
||||
static const NLType nfnl_nft_rule_types[] = {
|
||||
[NFTA_RULE_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_RULE_CHAIN] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_RULE_EXPRESSIONS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_expr_type_system }
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_rule);
|
||||
|
||||
static const NLType nfnl_nft_set_types[] = {
|
||||
[NFTA_SET_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_NAME] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_KEY_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_KEY_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_DATA_TYPE] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_DATA_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_POLICY] = { .type = NETLINK_TYPE_U32 },
|
||||
[NFTA_SET_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_set);
|
||||
|
||||
static const NLType nfnl_nft_setelem_types[] = {
|
||||
[NFTA_SET_ELEM_KEY] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_SET_ELEM_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_data_type_system },
|
||||
[NFTA_SET_ELEM_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_setelem);
|
||||
|
||||
static const NLType nfnl_nft_setelem_list_types[] = {
|
||||
[NFTA_SET_ELEM_LIST_TABLE] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_ELEM_LIST_SET] = { .type = NETLINK_TYPE_STRING, .size = NFT_TABLE_MAXNAMELEN - 1 },
|
||||
[NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_nft_setelem_list);
|
||||
|
||||
static const NLType nfnl_subsys_nft_types [] = {
|
||||
[NFT_MSG_DELTABLE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWTABLE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_table_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWCHAIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_chain_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_rule_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWSET] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_set_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_NEWSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFT_MSG_DELSETELEM] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_nft_setelem_list_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_subsys_nft);
|
||||
|
||||
static const NLType nfnl_msg_batch_types [] = {
|
||||
[NFNL_BATCH_GENID] = { .type = NETLINK_TYPE_U32 }
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_msg_batch);
|
||||
|
||||
static const NLType nfnl_subsys_none_types[] = {
|
||||
[NFNL_MSG_BATCH_BEGIN] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
[NFNL_MSG_BATCH_END] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_msg_batch_type_system, .size = sizeof(struct nfgenmsg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl_subsys_none);
|
||||
|
||||
static const NLType nfnl_types[] = {
|
||||
[NFNL_SUBSYS_NONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_none_type_system },
|
||||
[NFNL_SUBSYS_NFTABLES] = { .type = NETLINK_TYPE_NESTED, .type_system = &nfnl_subsys_nft_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(nfnl);
|
||||
|
||||
const NLType *nfnl_get_type(uint16_t nlmsg_type) {
|
||||
const NLTypeSystem *subsys;
|
||||
|
||||
subsys = type_system_get_type_system(&nfnl_type_system, nlmsg_type >> 8);
|
||||
if (!subsys)
|
||||
return NULL;
|
||||
|
||||
return type_system_get_type(subsys, nlmsg_type & ((1U << 8) - 1));
|
||||
}
|
||||
@ -1,872 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/batman_adv.h>
|
||||
#include <linux/can/netlink.h>
|
||||
#include <linux/can/vxcan.h>
|
||||
#include <linux/fib_rules.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if_addrlabel.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/if_tunnel.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/nexthop.h>
|
||||
#include <linux/nl80211.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/veth.h>
|
||||
#include <linux/wireguard.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "netlink-types-internal.h"
|
||||
#include "string-table.h"
|
||||
|
||||
/* Maximum ARP IP target defined in kernel */
|
||||
#define BOND_MAX_ARP_TARGETS 16
|
||||
|
||||
typedef enum {
|
||||
BOND_ARP_TARGETS_0,
|
||||
BOND_ARP_TARGETS_1,
|
||||
BOND_ARP_TARGETS_2,
|
||||
BOND_ARP_TARGETS_3,
|
||||
BOND_ARP_TARGETS_4,
|
||||
BOND_ARP_TARGETS_5,
|
||||
BOND_ARP_TARGETS_6,
|
||||
BOND_ARP_TARGETS_7,
|
||||
BOND_ARP_TARGETS_8,
|
||||
BOND_ARP_TARGETS_9,
|
||||
BOND_ARP_TARGETS_10,
|
||||
BOND_ARP_TARGETS_11,
|
||||
BOND_ARP_TARGETS_12,
|
||||
BOND_ARP_TARGETS_13,
|
||||
BOND_ARP_TARGETS_14,
|
||||
BOND_ARP_TARGETS_MAX = BOND_MAX_ARP_TARGETS,
|
||||
} BondArpTargets;
|
||||
|
||||
static const NLTypeSystem rtnl_link_type_system;
|
||||
|
||||
static const NLType rtnl_link_info_data_batadv_types[] = {
|
||||
[IFLA_BATADV_ALGO_NAME] = { .type = NETLINK_TYPE_STRING, .size = 20 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_veth_types[] = {
|
||||
[VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vxcan_types[] = {
|
||||
[VXCAN_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvlan_types[] = {
|
||||
[IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_macvlan_macaddr_types[] = {
|
||||
[IFLA_MACVLAN_MACADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_macvlan_macaddr);
|
||||
|
||||
static const NLType rtnl_link_info_data_macvlan_types[] = {
|
||||
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_MACVLAN_MACADDR_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_MACADDR_DATA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_macvlan_macaddr_type_system },
|
||||
[IFLA_MACVLAN_MACADDR_COUNT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NETLINK_TYPE_REJECT },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bridge_types[] = {
|
||||
[IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_AGEING_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_STP_STATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_VLAN_FILTERING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_ROOT_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_ROOT_PATH_COST] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE_DETECTED] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_HELLO_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_TCN_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_TOPOLOGY_CHANGE_TIMER] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_GC_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_GROUP_ADDR] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_FDB_FLUSH] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_SNOOPING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_QUERY_USE_IFADDR] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_QUERIER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_MCAST_HASH_ELASTICITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MCAST_HASH_MAX] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_LAST_MEMBER_CNT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MCAST_STARTUP_QUERY_CNT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_LAST_MEMBER_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_MEMBERSHIP_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERIER_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_MCAST_STARTUP_QUERY_INTVL] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BR_NF_CALL_IPTABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_NF_CALL_IP6TABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_NF_CALL_ARPTABLES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BR_VLAN_DEFAULT_PVID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BR_MCAST_IGMP_VERSION] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_vlan_qos_map_types[] = {
|
||||
[IFLA_VLAN_QOS_MAPPING] = { .size = sizeof(struct ifla_vlan_qos_mapping) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vlan_qos_map);
|
||||
|
||||
static const NLType rtnl_link_info_data_vlan_types[] = {
|
||||
[IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_VLAN_FLAGS] = { .size = sizeof(struct ifla_vlan_flags) },
|
||||
[IFLA_VLAN_EGRESS_QOS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
|
||||
[IFLA_VLAN_INGRESS_QOS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vlan_qos_map_type_system },
|
||||
[IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vxlan_types[] = {
|
||||
[IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_LEARNING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_AGEING] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_PORT_RANGE] = { .type = NETLINK_TYPE_U32},
|
||||
[IFLA_VXLAN_PROXY] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_RSC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_L2MISS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_L3MISS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_VXLAN_GROUP6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_LOCAL6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_REMCSUM_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_REMCSUM_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_GBP] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_COLLECT_METADATA] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_VXLAN_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_GPE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_TTL_INHERIT] = { .type = NETLINK_TYPE_FLAG },
|
||||
[IFLA_VXLAN_DF] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_bond_arp_target_types[] = {
|
||||
[BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_3] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_4] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_5] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_6] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_7] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_8] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_9] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_10] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_11] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_12] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_13] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_14] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_MAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_bond_arp_target);
|
||||
|
||||
static const NLType rtnl_link_info_data_bond_types[] = {
|
||||
[IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_UPDELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_DOWNDELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_USE_CARRIER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ARP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_ARP_IP_TARGET] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_bond_arp_target_type_system },
|
||||
[IFLA_BOND_ARP_VALIDATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_ARP_ALL_TARGETS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PRIMARY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PRIMARY_RESELECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_FAIL_OVER_MAC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_XMIT_HASH_POLICY] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_RESEND_IGMP] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_NUM_PEER_NOTIF] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ALL_SLAVES_ACTIVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_MIN_LINKS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_LP_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_PACKETS_PER_SLAVE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_AD_LACP_RATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_AD_SELECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
|
||||
[IFLA_BOND_AD_ACTOR_SYS_PRIO] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BOND_AD_USER_PORT_KEY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_iptun_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_6RD_PREFIX] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_6RD_RELAY_PREFIX] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_6RD_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipgre_types[] = {
|
||||
[IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_IKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_OKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GRE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GRE_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_PMTUDISC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GRE_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_ERSPAN_INDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvti_types[] = {
|
||||
[IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ip6tnl_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_ENCAP_LIMIT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_IPTUN_FLOWINFO] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vrf_types[] = {
|
||||
[IFLA_VRF_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_geneve_types[] = {
|
||||
[IFLA_GENEVE_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GENEVE_TTL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_TOS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GENEVE_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GENEVE_REMOTE6] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_GENEVE_UDP_CSUM] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GENEVE_TTL_INHERIT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_GENEVE_DF] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_can_types[] = {
|
||||
[IFLA_CAN_BITTIMING] = { .size = sizeof(struct can_bittiming) },
|
||||
[IFLA_CAN_RESTART_MS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_CAN_CTRLMODE] = { .size = sizeof(struct can_ctrlmode) },
|
||||
[IFLA_CAN_TERMINATION] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_macsec_types[] = {
|
||||
[IFLA_MACSEC_SCI] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_MACSEC_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_MACSEC_ICV_LEN] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_CIPHER_SUITE] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_MACSEC_WINDOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACSEC_ENCODING_SA] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_ENCRYPT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_INC_SCI] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_ES] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_SCB] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_REPLAY_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_MACSEC_VALIDATION] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_xfrm_types[] = {
|
||||
[IFLA_XFRM_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_XFRM_IF_ID] = { .type = NETLINK_TYPE_U32 }
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bareudp_types[] = {
|
||||
[IFLA_BAREUDP_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_ETHERTYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_SRCPORT_MIN] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BAREUDP_MULTIPROTO_MODE] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_link_info_data_type_systems[] = {
|
||||
{ .name = "bareudp", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bareudp), },
|
||||
{ .name = "batadv", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_batadv), },
|
||||
{ .name = "bond", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bond), },
|
||||
{ .name = "bridge", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_bridge), },
|
||||
{ .name = "can", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_can), },
|
||||
{ .name = "dummy", },
|
||||
{ .name = "erspan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "geneve", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_geneve), },
|
||||
{ .name = "gre", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "gretap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ifb", },
|
||||
{ .name = "ip6gre", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ip6gretap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipgre), },
|
||||
{ .name = "ip6tnl", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ip6tnl), },
|
||||
{ .name = "ipip", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun), },
|
||||
{ .name = "ipvlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan), },
|
||||
{ .name = "ipvtap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvlan), },
|
||||
{ .name = "macsec", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macsec), },
|
||||
{ .name = "macvlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
|
||||
{ .name = "macvtap", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_macvlan), },
|
||||
{ .name = "netdevsim", },
|
||||
{ .name = "nlmon", },
|
||||
{ .name = "sit", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_iptun), },
|
||||
{ .name = "vcan", },
|
||||
{ .name = "veth", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_veth), },
|
||||
{ .name = "vlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vlan), },
|
||||
{ .name = "vrf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vrf), },
|
||||
{ .name = "vti", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvti), },
|
||||
{ .name = "vti6", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_ipvti), },
|
||||
{ .name = "vxcan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxcan), },
|
||||
{ .name = "vxlan", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_vxlan), },
|
||||
{ .name = "wireguard", },
|
||||
{ .name = "xfrm", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_link_info_data_xfrm), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_link_info_data, IFLA_INFO_KIND);
|
||||
|
||||
static const NLType rtnl_link_info_types[] = {
|
||||
[IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union },
|
||||
/*
|
||||
[IFLA_INFO_XSTATS],
|
||||
[IFLA_INFO_SLAVE_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_INFO_SLAVE_DATA] = { .type = NETLINK_TYPE_NESTED },
|
||||
*/
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_link_info);
|
||||
|
||||
static const struct NLType rtnl_prot_info_bridge_port_types[] = {
|
||||
[IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_GUARD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROTECT] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_FAST_LEAVE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_LEARNING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PROXYARP_WIFI] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ROOT_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BRIDGE_ID] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_DESIGNATED_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_DESIGNATED_COST] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NO] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_CONFIG_PENDING] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MESSAGE_AGE_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FORWARD_DELAY_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_HOLD_TIMER] = { .type = NETLINK_TYPE_U64 },
|
||||
[IFLA_BRPORT_FLUSH] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_PAD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_VLAN_TUNNEL] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BCAST_FLOOD] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_GROUP_FWD_MASK] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRPORT_NEIGH_SUPPRESS] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_ISOLATED] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_BACKUP_PORT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_prot_info_type_systems[] = {
|
||||
{ .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_prot_info_bridge_port), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_prot_info);
|
||||
|
||||
static const struct NLType rtnl_af_spec_inet6_types[] = {
|
||||
[IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
IFLA_INET6_CONF,
|
||||
IFLA_INET6_STATS,
|
||||
IFLA_INET6_MCAST,
|
||||
IFLA_INET6_CACHEINFO,
|
||||
IFLA_INET6_ICMP6STATS,
|
||||
*/
|
||||
[IFLA_INET6_TOKEN] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_INET6_ADDR_GEN_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_af_spec_inet6);
|
||||
|
||||
static const NLType rtnl_af_spec_unspec_types[] = {
|
||||
[AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system },
|
||||
};
|
||||
|
||||
static const NLType rtnl_af_spec_bridge_types[] = {
|
||||
[IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRIDGE_VLAN_INFO] = { .size = sizeof(struct bridge_vlan_info) },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_af_spec_type_systems[] = {
|
||||
{ .protocol = AF_UNSPEC, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_unspec), },
|
||||
{ .protocol = AF_BRIDGE, .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_af_spec_bridge), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_PROTOCOL(rtnl_af_spec);
|
||||
|
||||
static const NLType rtnl_prop_list_types[] = {
|
||||
[IFLA_ALT_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_prop_list);
|
||||
|
||||
static const NLType rtnl_vf_vlan_list_types[] = {
|
||||
[IFLA_VF_VLAN_INFO] = { .size = sizeof(struct ifla_vf_vlan_info) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vf_vlan_list);
|
||||
|
||||
static const NLType rtnl_vf_info_types[] = {
|
||||
[IFLA_VF_MAC] = { .size = sizeof(struct ifla_vf_mac) },
|
||||
[IFLA_VF_VLAN] = { .size = sizeof(struct ifla_vf_vlan) },
|
||||
[IFLA_VF_VLAN_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_vlan_list_type_system},
|
||||
[IFLA_VF_TX_RATE] = { .size = sizeof(struct ifla_vf_tx_rate) },
|
||||
[IFLA_VF_SPOOFCHK] = { .size = sizeof(struct ifla_vf_spoofchk) },
|
||||
[IFLA_VF_RATE] = { .size = sizeof(struct ifla_vf_rate) },
|
||||
[IFLA_VF_LINK_STATE] = { .size = sizeof(struct ifla_vf_link_state) },
|
||||
[IFLA_VF_RSS_QUERY_EN] = { .size = sizeof(struct ifla_vf_rss_query_en) },
|
||||
[IFLA_VF_TRUST] = { .size = sizeof(struct ifla_vf_trust) },
|
||||
[IFLA_VF_IB_NODE_GUID] = { .size = sizeof(struct ifla_vf_guid) },
|
||||
[IFLA_VF_IB_PORT_GUID] = { .size = sizeof(struct ifla_vf_guid) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vf_info);
|
||||
|
||||
static const NLType rtnl_vfinfo_list_types[] = {
|
||||
[IFLA_VF_INFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vf_info_type_system },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_vfinfo_list);
|
||||
|
||||
static const NLType rtnl_link_types[] = {
|
||||
[IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
[IFLA_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_QDISC] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_STATS] = { .size = sizeof(struct rtnl_link_stats) },
|
||||
/*
|
||||
[IFLA_COST],
|
||||
[IFLA_PRIORITY],
|
||||
*/
|
||||
[IFLA_MASTER] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
[IFLA_WIRELESS],
|
||||
*/
|
||||
[IFLA_PROTINFO] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_prot_info_type_system_union },
|
||||
[IFLA_TXQLEN] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
[IFLA_MAP] = { .len = sizeof(struct rtnl_link_ifmap) },
|
||||
*/
|
||||
[IFLA_WEIGHT] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_OPERSTATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_LINKMODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_LINKINFO] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_info_type_system },
|
||||
[IFLA_NET_NS_PID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IFALIAS] = { .type = NETLINK_TYPE_STRING, .size = IFALIASZ - 1 },
|
||||
[IFLA_NUM_VF] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VFINFO_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_vfinfo_list_type_system },
|
||||
[IFLA_STATS64] = { .size = sizeof(struct rtnl_link_stats64) },
|
||||
/*
|
||||
[IFLA_VF_PORTS] = { .type = NETLINK_TYPE_NESTED },
|
||||
[IFLA_PORT_SELF] = { .type = NETLINK_TYPE_NESTED },
|
||||
*/
|
||||
[IFLA_AF_SPEC] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_af_spec_type_system_union },
|
||||
/*
|
||||
[IFLA_VF_PORTS],
|
||||
[IFLA_PORT_SELF],
|
||||
*/
|
||||
[IFLA_GROUP] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NET_NS_FD] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_EXT_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_PROMISCUITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NUM_TX_QUEUES] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_NUM_RX_QUEUES] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GSO_MAX_SEGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GSO_MAX_SIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_CARRIER] = { .type = NETLINK_TYPE_U8 },
|
||||
/*
|
||||
[IFLA_PHYS_PORT_ID] = { .type = NETLINK_TYPE_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
|
||||
*/
|
||||
[IFLA_MIN_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MAX_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_PROP_LIST] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_prop_list_type_system },
|
||||
[IFLA_ALT_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_link);
|
||||
|
||||
/* IFA_FLAGS was defined in kernel 3.14, but we still support older
|
||||
* kernels where IFA_MAX is lower. */
|
||||
static const NLType rtnl_address_types[] = {
|
||||
[IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
[IFA_BROADCAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_ANYCAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct ifa_cacheinfo) },
|
||||
[IFA_MULTICAST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFA_RT_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFA_TARGET_NETNSID] = { .type = NETLINK_TYPE_S32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_address);
|
||||
|
||||
/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
|
||||
|
||||
static const NLType rtnl_route_metrics_types[] = {
|
||||
[RTAX_MTU] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_WINDOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTT] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTTVAR] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_SSTHRESH] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_CWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_ADVMSS] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_REORDERING] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_HOPLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_INITCWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_FEATURES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_RTO_MIN] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_INITRWND] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_QUICKACK] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_CC_ALGO] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTAX_FASTOPEN_NO_COOKIE] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_route_metrics);
|
||||
|
||||
static const NLType rtnl_route_types[] = {
|
||||
[RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_IIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_OIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[RTA_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_PREFSRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_METRICS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_metrics_type_system},
|
||||
[RTA_MULTIPATH] = { .size = sizeof(struct rtnexthop) },
|
||||
[RTA_FLOW] = { .type = NETLINK_TYPE_U32 }, /* 6? */
|
||||
[RTA_CACHEINFO] = { .size = sizeof(struct rta_cacheinfo) },
|
||||
[RTA_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_MARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_MFC_STATS] = { .type = NETLINK_TYPE_U64 },
|
||||
[RTA_VIA] = { /* See struct rtvia */ },
|
||||
[RTA_NEWDST] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_ENCAP] = { .type = NETLINK_TYPE_NESTED }, /* Multiple type systems i.e. LWTUNNEL_ENCAP_MPLS/LWTUNNEL_ENCAP_IP/LWTUNNEL_ENCAP_ILA etc... */
|
||||
[RTA_EXPIRES] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_UID] = { .type = NETLINK_TYPE_U32 },
|
||||
[RTA_TTL_PROPAGATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[RTA_SPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[RTA_NH_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_route);
|
||||
|
||||
static const NLType rtnl_neigh_types[] = {
|
||||
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NDA_LLADDR] = { /* struct ether_addr, struct in_addr, or struct in6_addr */ },
|
||||
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
|
||||
[NDA_PROBES] = { .type = NETLINK_TYPE_U32 },
|
||||
[NDA_VLAN] = { .type = NETLINK_TYPE_U16 },
|
||||
[NDA_PORT] = { .type = NETLINK_TYPE_U16 },
|
||||
[NDA_VNI] = { .type = NETLINK_TYPE_U32 },
|
||||
[NDA_IFINDEX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_neigh);
|
||||
|
||||
static const NLType rtnl_addrlabel_types[] = {
|
||||
[IFAL_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR, .size = sizeof(struct in6_addr) },
|
||||
[IFAL_LABEL] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_addrlabel);
|
||||
|
||||
static const NLType rtnl_routing_policy_rule_types[] = {
|
||||
[FRA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FRA_SRC] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[FRA_IIFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[FRA_GOTO] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_PRIORITY] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FWMARK] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FLOW] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_TUN_ID] = { .type = NETLINK_TYPE_U64 },
|
||||
[FRA_SUPPRESS_IFGROUP] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_SUPPRESS_PREFIXLEN] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_TABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_FWMASK] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_OIFNAME] = { .type = NETLINK_TYPE_STRING },
|
||||
[FRA_PAD] = { .type = NETLINK_TYPE_U32 },
|
||||
[FRA_L3MDEV] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_UID_RANGE] = { .size = sizeof(struct fib_rule_uid_range) },
|
||||
[FRA_PROTOCOL] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_IP_PROTO] = { .type = NETLINK_TYPE_U8 },
|
||||
[FRA_SPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
|
||||
[FRA_DPORT_RANGE] = { .size = sizeof(struct fib_rule_port_range) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_routing_policy_rule);
|
||||
|
||||
static const NLType rtnl_nexthop_types[] = {
|
||||
[NHA_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GROUP] = { /* array of struct nexthop_grp */ },
|
||||
[NHA_GROUP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_BLACKHOLE] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_OIF] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_GATEWAY] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NHA_ENCAP_TYPE] = { .type = NETLINK_TYPE_U16 },
|
||||
[NHA_ENCAP] = { .type = NETLINK_TYPE_NESTED },
|
||||
[NHA_GROUPS] = { .type = NETLINK_TYPE_FLAG },
|
||||
[NHA_MASTER] = { .type = NETLINK_TYPE_U32 },
|
||||
[NHA_FDB] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_nexthop);
|
||||
|
||||
static const NLType rtnl_tca_option_data_cake_types[] = {
|
||||
[TCA_CAKE_BASE_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_CAKE_OVERHEAD] = { .type = NETLINK_TYPE_S32 },
|
||||
[TCA_CAKE_MPU] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_codel_types[] = {
|
||||
[TCA_CODEL_TARGET] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_ECN] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_CODEL_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_drr_types[] = {
|
||||
[TCA_DRR_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_quanta_types[] = {
|
||||
[TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32, },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_quanta);
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_prio_types[] = {
|
||||
[TCA_ETS_PRIOMAP_BAND] = { .type = NETLINK_TYPE_U8, },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca_option_data_ets_prio);
|
||||
|
||||
static const NLType rtnl_tca_option_data_ets_types[] = {
|
||||
[TCA_ETS_NBANDS] = { .type = NETLINK_TYPE_U8 },
|
||||
[TCA_ETS_NSTRICT] = { .type = NETLINK_TYPE_U8 },
|
||||
[TCA_ETS_QUANTA] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_quanta_type_system },
|
||||
[TCA_ETS_PRIOMAP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_option_data_ets_prio_type_system },
|
||||
[TCA_ETS_QUANTA_BAND] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_types[] = {
|
||||
[TCA_FQ_PLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_PLIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_INITIAL_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_RATE_ENABLE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_DEFAULT_RATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_MAX_RATE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_BUCKETS_LOG] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_FLOW_REFILL_DELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_LOW_RATE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_ORPHAN_MASK] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_codel_types[] = {
|
||||
[TCA_FQ_CODEL_TARGET] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_INTERVAL] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_ECN] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_FLOWS] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_QUANTUM] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_CE_THRESHOLD] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_DROP_BATCH_SIZE] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_FQ_CODEL_MEMORY_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_fq_pie_types[] = {
|
||||
[TCA_FQ_PIE_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_gred_types[] = {
|
||||
[TCA_GRED_DPS] = { .size = sizeof(struct tc_gred_sopt) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_hhf_types[] = {
|
||||
[TCA_HHF_BACKLOG_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_htb_types[] = {
|
||||
[TCA_HTB_PARMS] = { .size = sizeof(struct tc_htb_opt) },
|
||||
[TCA_HTB_INIT] = { .size = sizeof(struct tc_htb_glob) },
|
||||
[TCA_HTB_CTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_HTB_RTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_HTB_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_HTB_CEIL64] = { .type = NETLINK_TYPE_U64 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_pie_types[] = {
|
||||
[TCA_PIE_LIMIT] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_qfq_types[] = {
|
||||
[TCA_QFQ_WEIGHT] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_QFQ_LMAX] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_sfb_types[] = {
|
||||
[TCA_SFB_PARMS] = { .size = sizeof(struct tc_sfb_qopt) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_tca_option_data_tbf_types[] = {
|
||||
[TCA_TBF_PARMS] = { .size = sizeof(struct tc_tbf_qopt) },
|
||||
[TCA_TBF_RTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_TBF_PTAB] = { .size = TC_RTAB_SIZE },
|
||||
[TCA_TBF_RATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_TBF_PRATE64] = { .type = NETLINK_TYPE_U64 },
|
||||
[TCA_TBF_BURST] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_TBF_PBURST] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
static const NLTypeSystemUnionElement rtnl_tca_option_data_type_systems[] = {
|
||||
{ .name = "cake", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_cake), },
|
||||
{ .name = "codel", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_codel), },
|
||||
{ .name = "drr", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_drr), },
|
||||
{ .name = "ets", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_ets), },
|
||||
{ .name = "fq", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq), },
|
||||
{ .name = "fq_codel", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_codel), },
|
||||
{ .name = "fq_pie", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_fq_pie), },
|
||||
{ .name = "gred", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_gred), },
|
||||
{ .name = "hhf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_hhf), },
|
||||
{ .name = "htb", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_htb), },
|
||||
{ .name = "pie", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_pie), },
|
||||
{ .name = "qfq", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_qfq), },
|
||||
{ .name = "sfb", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_sfb), },
|
||||
{ .name = "tbf", .type_system = TYPE_SYSTEM_FROM_TYPE(rtnl_tca_option_data_tbf), },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM_UNION_MATCH_SIBLING(rtnl_tca_option_data, TCA_KIND);
|
||||
|
||||
static const NLType rtnl_tca_types[] = {
|
||||
[TCA_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[TCA_OPTIONS] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_tca_option_data_type_system_union },
|
||||
[TCA_INGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 },
|
||||
[TCA_EGRESS_BLOCK] = { .type = NETLINK_TYPE_U32 },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_tca);
|
||||
|
||||
static const NLType rtnl_mdb_types[] = {
|
||||
[MDBA_SET_ENTRY] = { .size = sizeof(struct br_port_msg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl_mdb);
|
||||
|
||||
static const NLType rtnl_types[] = {
|
||||
[RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_DELLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_GETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_SETLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_NEWLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_DELLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_GETLINKPROP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
[RTM_NEWADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_DELADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_GETADDR] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_address_type_system, .size = sizeof(struct ifaddrmsg) },
|
||||
[RTM_NEWROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_DELROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_GETROUTE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_route_type_system, .size = sizeof(struct rtmsg) },
|
||||
[RTM_NEWNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_DELNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_GETNEIGH] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_neigh_type_system, .size = sizeof(struct ndmsg) },
|
||||
[RTM_NEWADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_DELADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_GETADDRLABEL] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_addrlabel_type_system, .size = sizeof(struct ifaddrlblmsg) },
|
||||
[RTM_NEWRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_DELRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_GETRULE] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_routing_policy_rule_type_system, .size = sizeof(struct fib_rule_hdr) },
|
||||
[RTM_NEWNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_DELNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_GETNEXTHOP] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_nexthop_type_system, .size = sizeof(struct nhmsg) },
|
||||
[RTM_NEWQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_DELQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_GETQDISC] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_NEWTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_DELTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_GETTCLASS] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_tca_type_system, .size = sizeof(struct tcmsg) },
|
||||
[RTM_NEWMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
[RTM_DELMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
[RTM_GETMDB] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_mdb_type_system, .size = sizeof(struct br_port_msg) },
|
||||
};
|
||||
|
||||
DEFINE_TYPE_SYSTEM(rtnl);
|
||||
|
||||
const NLType *rtnl_get_type(uint16_t nlmsg_type) {
|
||||
return type_system_get_type(&rtnl_type_system, nlmsg_type);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-netlink.h"
|
||||
#include "macro.h"
|
||||
|
||||
enum {
|
||||
NETLINK_TYPE_UNSPEC,
|
||||
@ -35,30 +35,105 @@ typedef struct NLTypeSystemUnion NLTypeSystemUnion;
|
||||
typedef struct NLTypeSystem NLTypeSystem;
|
||||
typedef struct NLType NLType;
|
||||
|
||||
const NLType *rtnl_get_type(uint16_t nlmsg_type);
|
||||
const NLType *nfnl_get_type(uint16_t nlmsg_type);
|
||||
const NLTypeSystem *genl_get_type_system_by_name(const char *name);
|
||||
int genl_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t id,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size);
|
||||
struct NLTypeSystemUnion {
|
||||
int num;
|
||||
NLMatchType match_type;
|
||||
uint16_t match;
|
||||
int (*lookup)(const char *);
|
||||
const NLTypeSystem *type_systems;
|
||||
};
|
||||
|
||||
extern const NLTypeSystem genl_family_type_system_root;
|
||||
|
||||
uint16_t type_get_type(const NLType *type);
|
||||
size_t type_get_size(const NLType *type);
|
||||
const NLTypeSystem *type_get_type_system(const NLType *type);
|
||||
const NLTypeSystemUnion *type_get_type_system_union(const NLType *type);
|
||||
void type_get_type_system(const NLType *type, const NLTypeSystem **ret);
|
||||
void type_get_type_system_union(const NLType *type, const NLTypeSystemUnion **ret);
|
||||
|
||||
int type_system_root_get_type_system_and_header_size(
|
||||
sd_netlink *nl,
|
||||
uint16_t type,
|
||||
const NLTypeSystem **ret_type_system,
|
||||
size_t *ret_header_size);
|
||||
const NLTypeSystem* type_system_get_root(int protocol);
|
||||
uint16_t type_system_get_count(const NLTypeSystem *type_system);
|
||||
int type_system_root_get_type(sd_netlink *nl, const NLType **ret, uint16_t type);
|
||||
int type_system_get_type(const NLTypeSystem *type_system, const NLType **ret, uint16_t type);
|
||||
int type_system_get_type_system(const NLTypeSystem *type_system, const NLTypeSystem **ret, uint16_t type);
|
||||
int type_system_get_type_system_union(const NLTypeSystem *type_system, const NLTypeSystemUnion **ret, uint16_t type);
|
||||
int type_system_union_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, const char *key);
|
||||
int type_system_union_protocol_get_type_system(const NLTypeSystemUnion *type_system_union, const NLTypeSystem **ret, uint16_t protocol);
|
||||
|
||||
const NLType *type_system_get_type(const NLTypeSystem *type_system, uint16_t type);
|
||||
const NLTypeSystem *type_system_get_type_system(const NLTypeSystem *type_system, uint16_t type);
|
||||
const NLTypeSystemUnion *type_system_get_type_system_union(const NLTypeSystem *type_system, uint16_t type);
|
||||
NLMatchType type_system_union_get_match_type(const NLTypeSystemUnion *type_system_union);
|
||||
uint16_t type_system_union_get_match_attribute(const NLTypeSystemUnion *type_system_union);
|
||||
const NLTypeSystem *type_system_union_get_type_system_by_string(const NLTypeSystemUnion *type_system_union, const char *key);
|
||||
const NLTypeSystem *type_system_union_get_type_system_by_protocol(const NLTypeSystemUnion *type_system_union, uint16_t protocol);
|
||||
typedef enum NLUnionLinkInfoData {
|
||||
NL_UNION_LINK_INFO_DATA_BOND,
|
||||
NL_UNION_LINK_INFO_DATA_BRIDGE,
|
||||
NL_UNION_LINK_INFO_DATA_VLAN,
|
||||
NL_UNION_LINK_INFO_DATA_VETH,
|
||||
NL_UNION_LINK_INFO_DATA_DUMMY,
|
||||
NL_UNION_LINK_INFO_DATA_MACVLAN,
|
||||
NL_UNION_LINK_INFO_DATA_MACVTAP,
|
||||
NL_UNION_LINK_INFO_DATA_IPVLAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPVTAP,
|
||||
NL_UNION_LINK_INFO_DATA_VXLAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_ERSPAN,
|
||||
NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_SIT_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VTI6_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
|
||||
NL_UNION_LINK_INFO_DATA_VRF,
|
||||
NL_UNION_LINK_INFO_DATA_VCAN,
|
||||
NL_UNION_LINK_INFO_DATA_GENEVE,
|
||||
NL_UNION_LINK_INFO_DATA_VXCAN,
|
||||
NL_UNION_LINK_INFO_DATA_WIREGUARD,
|
||||
NL_UNION_LINK_INFO_DATA_NETDEVSIM,
|
||||
NL_UNION_LINK_INFO_DATA_CAN,
|
||||
NL_UNION_LINK_INFO_DATA_MACSEC,
|
||||
NL_UNION_LINK_INFO_DATA_NLMON,
|
||||
NL_UNION_LINK_INFO_DATA_XFRM,
|
||||
NL_UNION_LINK_INFO_DATA_IFB,
|
||||
NL_UNION_LINK_INFO_DATA_BAREUDP,
|
||||
NL_UNION_LINK_INFO_DATA_BATADV,
|
||||
_NL_UNION_LINK_INFO_DATA_MAX,
|
||||
_NL_UNION_LINK_INFO_DATA_INVALID = -EINVAL,
|
||||
} NLUnionLinkInfoData;
|
||||
|
||||
const char *nl_union_link_info_data_to_string(NLUnionLinkInfoData p) _const_;
|
||||
NLUnionLinkInfoData nl_union_link_info_data_from_string(const char *p) _pure_;
|
||||
|
||||
typedef enum NLUnionTCAOptionData {
|
||||
NL_UNION_TCA_OPTION_DATA_CAKE,
|
||||
NL_UNION_TCA_OPTION_DATA_CODEL,
|
||||
NL_UNION_TCA_OPTION_DATA_DRR,
|
||||
NL_UNION_TCA_OPTION_DATA_ETS,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ_CODEL,
|
||||
NL_UNION_TCA_OPTION_DATA_FQ_PIE,
|
||||
NL_UNION_TCA_OPTION_DATA_GRED,
|
||||
NL_UNION_TCA_OPTION_DATA_HHF,
|
||||
NL_UNION_TCA_OPTION_DATA_HTB,
|
||||
NL_UNION_TCA_OPTION_DATA_PIE,
|
||||
NL_UNION_TCA_OPTION_DATA_QFQ,
|
||||
NL_UNION_TCA_OPTION_DATA_SFB,
|
||||
NL_UNION_TCA_OPTION_DATA_TBF,
|
||||
_NL_UNION_TCA_OPTION_DATA_MAX,
|
||||
_NL_UNION_TCA_OPTION_DATA_INVALID = -EINVAL,
|
||||
} NLUnionTCAOptionData;
|
||||
|
||||
const char *nl_union_tca_option_data_to_string(NLUnionTCAOptionData p) _const_;
|
||||
NLUnionTCAOptionData nl_union_tca_option_data_from_string(const char *p) _pure_;
|
||||
|
||||
typedef enum NLUnionNFTExprData {
|
||||
NL_UNION_NFT_EXPR_DATA_BITWISE,
|
||||
NL_UNION_NFT_EXPR_DATA_CMP,
|
||||
NL_UNION_NFT_EXPR_DATA_FIB,
|
||||
NL_UNION_NFT_EXPR_DATA_LOOKUP,
|
||||
NL_UNION_NFT_EXPR_DATA_PAYLOAD,
|
||||
NL_UNION_NFT_EXPR_DATA_MASQ,
|
||||
NL_UNION_NFT_EXPR_DATA_META,
|
||||
NL_UNION_NFT_EXPR_DATA_NAT,
|
||||
_NL_UNION_NFT_EXPR_DATA_MAX,
|
||||
_NL_UNION_NFT_EXPR_DATA_INVALID = -EINVAL,
|
||||
} NLUnionNFTExprData;
|
||||
|
||||
const char *nl_union_nft_expr_data_to_string(NLUnionNFTExprData p) _const_;
|
||||
NLUnionNFTExprData nl_union_nft_expr_data_from_string(const char *p) _pure_;
|
||||
|
||||
@ -400,6 +400,25 @@ int rtnl_get_link_info(sd_netlink **rtnl, int ifindex, unsigned short *ret_iftyp
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret) {
|
||||
struct nlmsgerr *err;
|
||||
int r;
|
||||
|
||||
assert(error <= 0);
|
||||
|
||||
r = message_new(rtnl, ret, NLMSG_ERROR);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rtnl_message_seal(*ret);
|
||||
(*ret)->hdr->nlmsg_seq = serial;
|
||||
|
||||
err = NLMSG_DATA((*ret)->hdr);
|
||||
err->error = error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_log_parse_error(int r) {
|
||||
return log_error_errno(r, "Failed to parse netlink message: %m");
|
||||
}
|
||||
|
||||
@ -29,6 +29,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
|
||||
|
||||
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
|
||||
|
||||
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
|
||||
uint32_t rtnl_message_get_serial(sd_netlink_message *m);
|
||||
void rtnl_message_seal(sd_netlink_message *m);
|
||||
|
||||
static inline bool rtnl_message_type_is_neigh(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH);
|
||||
}
|
||||
|
||||
@ -13,20 +13,48 @@
|
||||
#include "format-util.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-types.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t msg_type, uint16_t flags) {
|
||||
static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int family, uint16_t type, uint16_t flags) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const NLType *nl_type;
|
||||
size_t size;
|
||||
int r;
|
||||
|
||||
assert_return(nfnl, -EINVAL);
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(nfnl, &m, NFNL_SUBSYS_NFTABLES << 8 | msg_type);
|
||||
r = type_system_root_get_type(nfnl, &nl_type, NFNL_SUBSYS_NFTABLES);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hdr->nlmsg_flags |= flags;
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = message_new_empty(nfnl, &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
size = NLMSG_SPACE(type_get_size(nl_type));
|
||||
|
||||
assert(size >= sizeof(struct nlmsghdr));
|
||||
m->hdr = malloc0(size);
|
||||
if (!m->hdr)
|
||||
return -ENOMEM;
|
||||
|
||||
m->hdr->nlmsg_flags = NLM_F_REQUEST | flags;
|
||||
|
||||
type_get_type_system(nl_type, &m->containers[0].type_system);
|
||||
|
||||
r = type_system_get_type_system(m->containers[0].type_system,
|
||||
&m->containers[0].type_system,
|
||||
type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m->hdr->nlmsg_len = size;
|
||||
m->hdr->nlmsg_type = NFNL_SUBSYS_NFTABLES << 8 | type;
|
||||
|
||||
*(struct nfgenmsg*) NLMSG_DATA(m->hdr) = (struct nfgenmsg) {
|
||||
.nfgen_family = family,
|
||||
@ -38,11 +66,11 @@ static int nft_message_new(sd_netlink *nfnl, sd_netlink_message **ret, int famil
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, uint16_t msg_type) {
|
||||
static int sd_nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, int v) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = message_new(nfnl, &m, NFNL_SUBSYS_NONE << 8 | msg_type);
|
||||
r = message_new(nfnl, &m, v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -53,31 +81,26 @@ static int nfnl_message_batch(sd_netlink *nfnl, sd_netlink_message **ret, uint16
|
||||
};
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret) {
|
||||
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
|
||||
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_BEGIN);
|
||||
}
|
||||
|
||||
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret) {
|
||||
return nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
|
||||
return sd_nfnl_message_batch(nfnl, ret, NFNL_MSG_BATCH_END);
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_basechain(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *chain,
|
||||
const char *table, const char *chain,
|
||||
const char *type,
|
||||
uint8_t hook,
|
||||
int prio) {
|
||||
|
||||
uint8_t hook, int prio) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWCHAIN, NLM_F_CREATE);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWCHAIN, NLM_F_CREATE | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -113,16 +136,12 @@ int sd_nfnl_nft_message_new_basechain(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_del_table(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table) {
|
||||
|
||||
int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELTABLE, NLM_F_CREATE);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELTABLE, NLM_F_CREATE | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -134,16 +153,12 @@ int sd_nfnl_nft_message_del_table(
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_table(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table) {
|
||||
|
||||
int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, uint16_t flags) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWTABLE, NLM_F_CREATE | NLM_F_EXCL);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWTABLE, NLM_F_CREATE | flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -155,17 +170,12 @@ int sd_nfnl_nft_message_new_table(
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_rule(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *chain) {
|
||||
|
||||
int sd_nfnl_nft_message_new_rule(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *chain) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWRULE, NLM_F_CREATE);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWRULE, NLM_F_CREATE | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -181,19 +191,13 @@ int sd_nfnl_nft_message_new_rule(
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_set(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name,
|
||||
uint32_t set_id,
|
||||
uint32_t klen) {
|
||||
|
||||
int sd_nfnl_nft_message_new_set(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name,
|
||||
uint32_t set_id, uint32_t klen) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSET, NLM_F_CREATE);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSET, NLM_F_CREATE | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -212,22 +216,16 @@ int sd_nfnl_nft_message_new_set(
|
||||
r = sd_netlink_message_append_u32(m, NFTA_SET_KEY_LEN, htobe32(klen));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_new_setelems_begin(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name) {
|
||||
|
||||
int sd_nfnl_nft_message_new_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSETELEM, NLM_F_CREATE);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_NEWSETELEM, NLM_F_CREATE | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -247,17 +245,12 @@ int sd_nfnl_nft_message_new_setelems_begin(
|
||||
return r;
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_del_setelems_begin(
|
||||
sd_netlink *nfnl,
|
||||
sd_netlink_message **ret,
|
||||
int family,
|
||||
const char *table,
|
||||
const char *set_name) {
|
||||
|
||||
int sd_nfnl_nft_message_del_setelems_begin(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *set_name) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
int r;
|
||||
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELSETELEM, 0);
|
||||
r = nft_message_new(nfnl, &m, family, NFT_MSG_DELSETELEM, NLM_F_ACK);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -278,9 +271,7 @@ int sd_nfnl_nft_message_del_setelems_begin(
|
||||
}
|
||||
|
||||
static int sd_nfnl_add_data(sd_netlink_message *m, uint16_t attr, const void *data, uint32_t dlen) {
|
||||
int r;
|
||||
|
||||
r = sd_netlink_message_open_container(m, attr);
|
||||
int r = sd_netlink_message_open_container(m, attr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -291,14 +282,9 @@ static int sd_nfnl_add_data(sd_netlink_message *m, uint16_t attr, const void *da
|
||||
return sd_netlink_message_close_container(m); /* attr */
|
||||
}
|
||||
|
||||
int sd_nfnl_nft_message_add_setelem(
|
||||
sd_netlink_message *m,
|
||||
uint32_t num,
|
||||
const void *key,
|
||||
uint32_t klen,
|
||||
const void *data,
|
||||
uint32_t dlen) {
|
||||
|
||||
int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m, uint32_t num,
|
||||
const void *key, uint32_t klen,
|
||||
const void *data, uint32_t dlen) {
|
||||
int r;
|
||||
|
||||
r = sd_netlink_message_open_array(m, num);
|
||||
@ -315,8 +301,7 @@ int sd_nfnl_nft_message_add_setelem(
|
||||
goto cancel;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
cancel:
|
||||
sd_netlink_message_cancel_array(m);
|
||||
return r;
|
||||
@ -271,13 +271,13 @@ int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
}
|
||||
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
uint16_t nlmsg_type, int nh_family,
|
||||
uint16_t nhmsg_type, int nh_family,
|
||||
unsigned char nh_protocol) {
|
||||
struct nhmsg *nhm;
|
||||
int r;
|
||||
|
||||
assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL);
|
||||
switch(nlmsg_type) {
|
||||
assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
|
||||
switch(nhmsg_type) {
|
||||
case RTM_DELNEXTHOP:
|
||||
assert_return(nh_family == AF_UNSPEC, -EINVAL);
|
||||
_fallthrough_;
|
||||
@ -292,11 +292,11 @@ int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
|
||||
}
|
||||
assert_return(ret, -EINVAL);
|
||||
|
||||
r = message_new(rtnl, ret, nlmsg_type);
|
||||
r = message_new(rtnl, ret, nhmsg_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (nlmsg_type == RTM_NEWNEXTHOP)
|
||||
if (nhmsg_type == RTM_NEWNEXTHOP)
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
|
||||
|
||||
nhm = NLMSG_DATA((*ret)->hdr);
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,40 +2,31 @@
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/fou.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/if_macsec.h>
|
||||
#include <linux/l2tp.h>
|
||||
#include <linux/nl80211.h>
|
||||
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "ether-addr-util.h"
|
||||
#include "macro.h"
|
||||
#include "netlink-genl.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "util.h"
|
||||
|
||||
static void test_message_link_bridge(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
uint32_t cost;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0);
|
||||
assert_se(sd_rtnl_message_link_set_family(message, AF_BRIDGE) >= 0);
|
||||
assert_se(sd_netlink_message_open_container(message, IFLA_PROTINFO) >= 0);
|
||||
assert_se(sd_netlink_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(message) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_rewind(message, rtnl) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(message, NULL) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(message, IFLA_PROTINFO) >= 0);
|
||||
assert_se(sd_netlink_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0);
|
||||
@ -49,8 +40,6 @@ static void test_link_configure(sd_netlink *rtnl, int ifindex) {
|
||||
const char *name_out;
|
||||
struct ether_addr mac_out;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
/* we'd really like to test NEWLINK, but let's not mess with the running kernel */
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0);
|
||||
|
||||
@ -68,8 +57,6 @@ static void test_link_get(sd_netlink *rtnl, int ifindex) {
|
||||
uint32_t u32_data;
|
||||
struct ether_addr eth_data;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0);
|
||||
assert_se(m);
|
||||
|
||||
@ -96,8 +83,6 @@ static void test_address_get(sd_netlink *rtnl, int ifindex) {
|
||||
struct ifa_cacheinfo cache;
|
||||
const char *label;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_addr(rtnl, &m, RTM_GETADDR, ifindex, AF_INET) >= 0);
|
||||
assert_se(m);
|
||||
assert_se(sd_netlink_message_request_dump(m, true) >= 0);
|
||||
@ -115,8 +100,6 @@ static void test_route(sd_netlink *rtnl) {
|
||||
uint32_t index = 2, u32_data;
|
||||
int r;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
r = sd_rtnl_message_new_route(rtnl, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");
|
||||
@ -137,7 +120,7 @@ static void test_route(sd_netlink *rtnl) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(sd_netlink_message_rewind(req, rtnl) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(req, NULL) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0);
|
||||
assert_se(addr_data.s_addr == addr.s_addr);
|
||||
@ -151,8 +134,6 @@ static void test_route(sd_netlink *rtnl) {
|
||||
static void test_multiple(void) {
|
||||
sd_netlink *rtnl1, *rtnl2;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl1) >= 0);
|
||||
assert_se(sd_netlink_open(&rtnl2) >= 0);
|
||||
|
||||
@ -183,8 +164,6 @@ static void test_event_loop(int ifindex) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo2");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -215,8 +194,6 @@ static void test_async(int ifindex) {
|
||||
const char *description;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -248,8 +225,6 @@ static void test_slot_set(int ifindex) {
|
||||
const char *description;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
ifname = strdup("lo");
|
||||
assert_se(ifname);
|
||||
|
||||
@ -328,8 +303,6 @@ static void test_async_destroy_callback(int ifindex) {
|
||||
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *slot = NULL;
|
||||
char *ifname;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(t = new(struct test_async_object, 1));
|
||||
assert_se(ifname = strdup("lo"));
|
||||
*t = (struct test_async_object) {
|
||||
@ -398,8 +371,6 @@ static void test_pipe(int ifindex) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL;
|
||||
int counter = 0;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl) >= 0);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0);
|
||||
@ -425,8 +396,6 @@ static void test_container(sd_netlink *rtnl) {
|
||||
uint32_t u32_data;
|
||||
const char *string_data;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0);
|
||||
@ -437,7 +406,7 @@ static void test_container(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(m) == -EINVAL);
|
||||
|
||||
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
|
||||
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(m, IFLA_LINKINFO) >= 0);
|
||||
assert_se(sd_netlink_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0);
|
||||
@ -460,8 +429,6 @@ static void test_match(void) {
|
||||
_cleanup_(sd_netlink_slot_unrefp) sd_netlink_slot *s1 = NULL, *s2 = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_add_match(rtnl, &s1, RTM_NEWLINK, link_handler, NULL, NULL, NULL) >= 0);
|
||||
@ -478,8 +445,6 @@ static void test_get_addresses(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
sd_netlink_message *m;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC) >= 0);
|
||||
assert_se(sd_netlink_message_request_dump(req, true) >= 0);
|
||||
assert_se(sd_netlink_call(rtnl, req, 0, &reply) >= 0);
|
||||
@ -507,9 +472,7 @@ static void test_get_addresses(sd_netlink *rtnl) {
|
||||
static void test_message(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
|
||||
assert_se(rtnl_message_new_synthetic_error(rtnl, -ETIMEDOUT, 1, &m) >= 0);
|
||||
assert_se(sd_netlink_message_get_errno(m) == -ETIMEDOUT);
|
||||
}
|
||||
|
||||
@ -517,10 +480,8 @@ static void test_array(void) {
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_genl_socket_open(&genl) >= 0);
|
||||
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
assert_se(sd_genl_message_new(genl, SD_GENL_ID_CTRL, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_open_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
@ -535,7 +496,7 @@ static void test_array(void) {
|
||||
}
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
|
||||
message_seal(m);
|
||||
rtnl_message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, genl) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(m, CTRL_ATTR_MCAST_GROUPS) >= 0);
|
||||
@ -561,8 +522,6 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
_cleanup_strv_free_ char **names_in = NULL, **names_out;
|
||||
const char *p;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1) >= 0);
|
||||
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
@ -576,8 +535,8 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, names_in) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(m) >= 0);
|
||||
|
||||
message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, rtnl) >= 0);
|
||||
rtnl_message_seal(m);
|
||||
assert_se(sd_netlink_message_rewind(m, NULL) >= 0);
|
||||
|
||||
assert_se(sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &names_out) >= 0);
|
||||
assert_se(strv_equal(names_in, names_out));
|
||||
@ -588,84 +547,6 @@ static void test_strv(sd_netlink *rtnl) {
|
||||
assert_se(sd_netlink_message_exit_container(m) >= 0);
|
||||
}
|
||||
|
||||
static int genl_ctrl_match_callback(sd_netlink *genl, sd_netlink_message *m, void *userdata) {
|
||||
const char *name;
|
||||
uint16_t id;
|
||||
uint8_t cmd;
|
||||
|
||||
assert(genl);
|
||||
assert(m);
|
||||
|
||||
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
|
||||
assert_se(streq(name, CTRL_GENL_NAME));
|
||||
|
||||
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
|
||||
|
||||
switch (cmd) {
|
||||
case CTRL_CMD_NEWFAMILY:
|
||||
case CTRL_CMD_DELFAMILY:
|
||||
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
|
||||
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
|
||||
log_debug("%s: %s (id=%"PRIu16") family is %s.",
|
||||
__func__, name, id, cmd == CTRL_CMD_NEWFAMILY ? "added" : "removed");
|
||||
break;
|
||||
case CTRL_CMD_NEWMCAST_GRP:
|
||||
case CTRL_CMD_DELMCAST_GRP:
|
||||
assert_se(sd_netlink_message_read_string(m, CTRL_ATTR_FAMILY_NAME, &name) >= 0);
|
||||
assert_se(sd_netlink_message_read_u16(m, CTRL_ATTR_FAMILY_ID, &id) >= 0);
|
||||
log_debug("%s: multicast group for %s (id=%"PRIu16") family is %s.",
|
||||
__func__, name, id, cmd == CTRL_CMD_NEWMCAST_GRP ? "added" : "removed");
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: received nlctrl message with unknown command '%"PRIu8"'.", __func__, cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_genl(void) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *genl = NULL;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
const char *name;
|
||||
uint8_t cmd;
|
||||
int r;
|
||||
|
||||
log_debug("/* %s */", __func__);
|
||||
|
||||
assert_se(sd_genl_socket_open(&genl) >= 0);
|
||||
assert_se(sd_event_default(&event) >= 0);
|
||||
assert_se(sd_netlink_attach_event(genl, event, 0) >= 0);
|
||||
|
||||
assert_se(sd_genl_message_new(genl, CTRL_GENL_NAME, CTRL_CMD_GETFAMILY, &m) >= 0);
|
||||
assert_se(sd_genl_message_get_family_name(genl, m, &name) >= 0);
|
||||
assert_se(streq(name, CTRL_GENL_NAME));
|
||||
assert_se(sd_genl_message_get_command(genl, m, &cmd) >= 0);
|
||||
assert_se(cmd == CTRL_CMD_GETFAMILY);
|
||||
|
||||
assert_se(sd_genl_add_match(genl, NULL, CTRL_GENL_NAME, "notify", 0, genl_ctrl_match_callback, NULL, NULL, "genl-ctrl-notify") >= 0);
|
||||
|
||||
m = sd_netlink_message_unref(m);
|
||||
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) < 0);
|
||||
assert_se(sd_genl_message_new(genl, "should-not-exist", CTRL_CMD_GETFAMILY, &m) == -EOPNOTSUPP);
|
||||
|
||||
/* These families may not be supported by kernel. Hence, ignore results. */
|
||||
(void) sd_genl_message_new(genl, FOU_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, L2TP_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, MACSEC_GENL_NAME, 0, &m);
|
||||
m = sd_netlink_message_unref(m);
|
||||
(void) sd_genl_message_new(genl, NL80211_GENL_NAME, 0, &m);
|
||||
|
||||
for (;;) {
|
||||
r = sd_event_run(event, 500 * USEC_PER_MSEC);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
sd_netlink *rtnl;
|
||||
sd_netlink_message *m;
|
||||
@ -674,8 +555,6 @@ int main(void) {
|
||||
int if_loopback;
|
||||
uint16_t type;
|
||||
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_match();
|
||||
test_multiple();
|
||||
|
||||
@ -726,7 +605,5 @@ int main(void) {
|
||||
assert_se((r = sd_netlink_message_unref(r)) == NULL);
|
||||
assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL);
|
||||
|
||||
test_genl();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ ENV{ID_SOFTWARE_RADIO}=="?*", TAG+="uaccess"
|
||||
# 3D printers, CNC machines, laser cutters, 3D scanners, etc.
|
||||
ENV{ID_MAKER_TOOL}=="?*", TAG+="uaccess"
|
||||
|
||||
# Protocol analyzers
|
||||
ENV{ID_PROTOCOL_ANALYZER}=="?*", TAG+="uaccess"
|
||||
# Protocol analysers
|
||||
ENV{ID_PROTOCOL_ANALYSER}=="?*", TAG+="uaccess"
|
||||
|
||||
LABEL="uaccess_end"
|
||||
|
||||
@ -122,7 +122,7 @@ static int netdev_batadv_post_create(NetDev *netdev, Link *link, sd_netlink_mess
|
||||
b = BATADV(netdev);
|
||||
assert(b);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, BATADV_NL_NAME, BATADV_CMD_SET_MESH, &message);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_BATADV, BATADV_CMD_SET_MESH, &message);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ static int netdev_fill_fou_tunnel_message(NetDev *netdev, sd_netlink_message **r
|
||||
|
||||
assert(t);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, FOU_GENL_NAME, FOU_CMD_ADD, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_FOU, FOU_CMD_ADD, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ static int netdev_l2tp_fill_message_tunnel(NetDev *netdev, union in_addr_union *
|
||||
|
||||
assert(t);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_TUNNEL_CREATE, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_TUNNEL_CREATE, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -195,7 +195,7 @@ static int netdev_l2tp_fill_message_session(NetDev *netdev, L2tpSession *session
|
||||
assert(session);
|
||||
assert(session->tunnel);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, L2TP_GENL_NAME, L2TP_CMD_SESSION_CREATE, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_L2TP, L2TP_CMD_SESSION_CREATE, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
|
||||
@ -224,7 +224,7 @@ static int netdev_macsec_fill_message(NetDev *netdev, int command, sd_netlink_me
|
||||
assert(netdev);
|
||||
assert(netdev->ifindex > 0);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, MACSEC_GENL_NAME, command, &m);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_MACSEC, command, &m);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to create generic netlink message: %m");
|
||||
|
||||
|
||||
@ -229,7 +229,7 @@ static int wireguard_set_interface(NetDev *netdev) {
|
||||
|
||||
message = sd_netlink_message_unref(message);
|
||||
|
||||
r = sd_genl_message_new(netdev->manager->genl, WG_GENL_NAME, WG_CMD_SET_DEVICE, &message);
|
||||
r = sd_genl_message_new(netdev->manager->genl, SD_GENL_WIREGUARD, WG_CMD_SET_DEVICE, &message);
|
||||
if (r < 0)
|
||||
return log_netdev_error_errno(netdev, r, "Failed to allocate generic netlink message: %m");
|
||||
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
#include "hostname-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "net-condition.h"
|
||||
#include "netdev/macvlan.h"
|
||||
#include "networkd-address-label.h"
|
||||
#include "networkd-address.h"
|
||||
#include "networkd-bridge-fdb.h"
|
||||
@ -171,33 +170,8 @@ int network_verify(Network *network) {
|
||||
network->routes_by_section = hashmap_free_with_destructor(network->routes_by_section, route_free);
|
||||
}
|
||||
|
||||
if (network->link_local < 0) {
|
||||
network->link_local = ADDRESS_FAMILY_IPV6;
|
||||
|
||||
if (network->bridge)
|
||||
network->link_local = ADDRESS_FAMILY_NO;
|
||||
else {
|
||||
NetDev *netdev;
|
||||
|
||||
HASHMAP_FOREACH(netdev, network->stacked_netdevs) {
|
||||
MacVlan *m;
|
||||
|
||||
if (netdev->kind == NETDEV_KIND_MACVLAN)
|
||||
m = MACVLAN(netdev);
|
||||
else if (netdev->kind == NETDEV_KIND_MACVTAP)
|
||||
m = MACVTAP(netdev);
|
||||
else
|
||||
continue;
|
||||
|
||||
if (m->mode == NETDEV_MACVLAN_MODE_PASSTHRU)
|
||||
network->link_local = ADDRESS_FAMILY_NO;
|
||||
|
||||
/* There won't be a passthru MACVLAN/MACVTAP if there's already one in another mode */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (network->link_local < 0)
|
||||
network->link_local = network->bridge ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_IPV6;
|
||||
if (network->ipv6ll_address_gen_mode == IPV6_LINK_LOCAL_ADDRESSS_GEN_MODE_NONE)
|
||||
SET_FLAG(network->link_local, ADDRESS_FAMILY_IPV6, false);
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "lldp-internal.h"
|
||||
#include "macvlan.h"
|
||||
#include "ndisc-internal.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-network.h"
|
||||
#include "networkd-util.h"
|
||||
@ -34,6 +35,7 @@ int main(int argc, char **argv) {
|
||||
/* test_table(link_state, LINK_STATE); — not a reversible mapping */
|
||||
test_table(lldp_mode, LLDP_MODE);
|
||||
test_table(netdev_kind, NETDEV_KIND);
|
||||
test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA);
|
||||
test_table(radv_prefix_delegation, RADV_PREFIX_DELEGATION);
|
||||
test_table(lldp_event, SD_LLDP_EVENT);
|
||||
test_table(ndisc_event, SD_NDISC_EVENT);
|
||||
@ -46,6 +48,7 @@ int main(int argc, char **argv) {
|
||||
assert_cc(sizeof(sd_lldp_event_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_ndisc_event_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_dhcp_lease_server_type_t) == sizeof(int64_t));
|
||||
assert_cc(sizeof(sd_genl_family_t) == sizeof(int64_t));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@ -932,131 +932,6 @@ int ethtool_set_flow_control(int *fd, const char *ifname, int rx, int tx, int au
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {
|
||||
struct ethtool_coalesce ecmd = {
|
||||
.cmd = ETHTOOL_GCOALESCE,
|
||||
};
|
||||
struct ifreq ifr = {
|
||||
.ifr_data = (void*) &ecmd,
|
||||
};
|
||||
bool need_update = false;
|
||||
int r;
|
||||
|
||||
assert(ethtool_fd);
|
||||
assert(ifname);
|
||||
assert(coalesce);
|
||||
|
||||
if (coalesce->use_adaptive_rx_coalesce < 0 &&
|
||||
coalesce->use_adaptive_tx_coalesce < 0 &&
|
||||
!coalesce->rx_coalesce_usecs.set &&
|
||||
!coalesce->rx_max_coalesced_frames.set &&
|
||||
!coalesce->rx_coalesce_usecs_irq.set &&
|
||||
!coalesce->rx_max_coalesced_frames_irq.set &&
|
||||
!coalesce->tx_coalesce_usecs.set &&
|
||||
!coalesce->tx_max_coalesced_frames.set &&
|
||||
!coalesce->tx_coalesce_usecs_irq.set &&
|
||||
!coalesce->tx_max_coalesced_frames_irq.set &&
|
||||
!coalesce->stats_block_coalesce_usecs.set &&
|
||||
!coalesce->pkt_rate_low.set &&
|
||||
!coalesce->rx_coalesce_usecs_low.set &&
|
||||
!coalesce->rx_max_coalesced_frames_low.set &&
|
||||
!coalesce->tx_coalesce_usecs_low.set &&
|
||||
!coalesce->tx_max_coalesced_frames_low.set &&
|
||||
!coalesce->pkt_rate_high.set &&
|
||||
!coalesce->rx_coalesce_usecs_high.set &&
|
||||
!coalesce->rx_max_coalesced_frames_high.set &&
|
||||
!coalesce->tx_coalesce_usecs_high.set &&
|
||||
!coalesce->tx_max_coalesced_frames_high.set &&
|
||||
!coalesce->rate_sample_interval.set)
|
||||
return 0;
|
||||
|
||||
r = ethtool_connect(ethtool_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
|
||||
|
||||
r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (coalesce->use_adaptive_rx_coalesce >= 0)
|
||||
UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);
|
||||
|
||||
if (coalesce->use_adaptive_tx_coalesce >= 0)
|
||||
UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_irq.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_irq.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_irq.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_irq.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);
|
||||
|
||||
if (coalesce->stats_block_coalesce_usecs.set)
|
||||
UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->pkt_rate_low.set)
|
||||
UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_low.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_low.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_low.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_low.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);
|
||||
|
||||
if (coalesce->pkt_rate_high.set)
|
||||
UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_high.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_high.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_high.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_high.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);
|
||||
|
||||
if (coalesce->rate_sample_interval.set)
|
||||
UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);
|
||||
|
||||
if (!need_update)
|
||||
return 0;
|
||||
|
||||
ecmd.cmd = ETHTOOL_SCOALESCE;
|
||||
r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_advertise(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -1307,3 +1182,128 @@ int config_parse_coalesce_sec(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ethtool_set_nic_coalesce_settings(int *ethtool_fd, const char *ifname, const netdev_coalesce_param *coalesce) {
|
||||
struct ethtool_coalesce ecmd = {
|
||||
.cmd = ETHTOOL_GCOALESCE,
|
||||
};
|
||||
struct ifreq ifr = {
|
||||
.ifr_data = (void*) &ecmd,
|
||||
};
|
||||
bool need_update = false;
|
||||
int r;
|
||||
|
||||
assert(ethtool_fd);
|
||||
assert(ifname);
|
||||
assert(coalesce);
|
||||
|
||||
if (coalesce->use_adaptive_rx_coalesce < 0 &&
|
||||
coalesce->use_adaptive_tx_coalesce < 0 &&
|
||||
!coalesce->rx_coalesce_usecs.set &&
|
||||
!coalesce->rx_max_coalesced_frames.set &&
|
||||
!coalesce->rx_coalesce_usecs_irq.set &&
|
||||
!coalesce->rx_max_coalesced_frames_irq.set &&
|
||||
!coalesce->tx_coalesce_usecs.set &&
|
||||
!coalesce->tx_max_coalesced_frames.set &&
|
||||
!coalesce->tx_coalesce_usecs_irq.set &&
|
||||
!coalesce->tx_max_coalesced_frames_irq.set &&
|
||||
!coalesce->stats_block_coalesce_usecs.set &&
|
||||
!coalesce->pkt_rate_low.set &&
|
||||
!coalesce->rx_coalesce_usecs_low.set &&
|
||||
!coalesce->rx_max_coalesced_frames_low.set &&
|
||||
!coalesce->tx_coalesce_usecs_low.set &&
|
||||
!coalesce->tx_max_coalesced_frames_low.set &&
|
||||
!coalesce->pkt_rate_high.set &&
|
||||
!coalesce->rx_coalesce_usecs_high.set &&
|
||||
!coalesce->rx_max_coalesced_frames_high.set &&
|
||||
!coalesce->tx_coalesce_usecs_high.set &&
|
||||
!coalesce->tx_max_coalesced_frames_high.set &&
|
||||
!coalesce->rate_sample_interval.set)
|
||||
return 0;
|
||||
|
||||
r = ethtool_connect(ethtool_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
|
||||
|
||||
r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
if (coalesce->use_adaptive_rx_coalesce >= 0)
|
||||
UPDATE(ecmd.use_adaptive_rx_coalesce, (uint32_t) coalesce->use_adaptive_rx_coalesce, need_update);
|
||||
|
||||
if (coalesce->use_adaptive_tx_coalesce >= 0)
|
||||
UPDATE(ecmd.use_adaptive_tx_coalesce, (uint32_t) coalesce->use_adaptive_tx_coalesce, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs, coalesce->rx_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames, coalesce->rx_max_coalesced_frames.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_irq.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_irq, coalesce->rx_coalesce_usecs_irq.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_irq.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_irq, coalesce->rx_max_coalesced_frames_irq.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs, coalesce->tx_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames, coalesce->tx_max_coalesced_frames.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_irq.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_irq, coalesce->tx_coalesce_usecs_irq.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_irq.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_irq, coalesce->tx_max_coalesced_frames_irq.value, need_update);
|
||||
|
||||
if (coalesce->stats_block_coalesce_usecs.set)
|
||||
UPDATE(ecmd.stats_block_coalesce_usecs, coalesce->stats_block_coalesce_usecs.value, need_update);
|
||||
|
||||
if (coalesce->pkt_rate_low.set)
|
||||
UPDATE(ecmd.pkt_rate_low, coalesce->pkt_rate_low.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_low.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_low, coalesce->rx_coalesce_usecs_low.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_low.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_low, coalesce->rx_max_coalesced_frames_low.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_low.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_low, coalesce->tx_coalesce_usecs_low.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_low.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_low, coalesce->tx_max_coalesced_frames_low.value, need_update);
|
||||
|
||||
if (coalesce->pkt_rate_high.set)
|
||||
UPDATE(ecmd.pkt_rate_high, coalesce->pkt_rate_high.value, need_update);
|
||||
|
||||
if (coalesce->rx_coalesce_usecs_high.set)
|
||||
UPDATE(ecmd.rx_coalesce_usecs_high, coalesce->rx_coalesce_usecs_high.value, need_update);
|
||||
|
||||
if (coalesce->rx_max_coalesced_frames_high.set)
|
||||
UPDATE(ecmd.rx_max_coalesced_frames_high, coalesce->rx_max_coalesced_frames_high.value, need_update);
|
||||
|
||||
if (coalesce->tx_coalesce_usecs_high.set)
|
||||
UPDATE(ecmd.tx_coalesce_usecs_high, coalesce->tx_coalesce_usecs_high.value, need_update);
|
||||
|
||||
if (coalesce->tx_max_coalesced_frames_high.set)
|
||||
UPDATE(ecmd.tx_max_coalesced_frames_high, coalesce->tx_max_coalesced_frames_high.value, need_update);
|
||||
|
||||
if (coalesce->rate_sample_interval.set)
|
||||
UPDATE(ecmd.rate_sample_interval, DIV_ROUND_UP(coalesce->rate_sample_interval.value, USEC_PER_SEC), need_update);
|
||||
|
||||
if (!need_update)
|
||||
return 0;
|
||||
|
||||
ecmd.cmd = ETHTOOL_SCOALESCE;
|
||||
r = ioctl(*ethtool_fd, SIOCETHTOOL, &ifr);
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -649,7 +649,7 @@ static int fw_nftables_init_family(sd_netlink *nfnl, int family) {
|
||||
msgcnt++;
|
||||
assert(msgcnt < NFT_INIT_MSGS);
|
||||
/* Set F_EXCL so table add fails if the table already exists. */
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME);
|
||||
r = sd_nfnl_nft_message_new_table(nfnl, &batch[msgcnt], family, NFT_SYSTEMD_TABLE_NAME, NLM_F_EXCL | NLM_F_ACK);
|
||||
if (r < 0)
|
||||
goto out_unref;
|
||||
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "log.h"
|
||||
#include "string-util.h"
|
||||
#include "wifi-util.h"
|
||||
|
||||
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
const char *family;
|
||||
sd_genl_family_t family;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(ifindex > 0);
|
||||
|
||||
r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_INTERFACE, &m);
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_INTERFACE, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -39,11 +38,11 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi interface %d: %m", ifindex);
|
||||
|
||||
r = sd_genl_message_get_family_name(genl, reply, &family);
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("Received message of unexpected genl family '%s', ignoring.", family);
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %" PRIi64 ", ignoring.", family);
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
@ -76,14 +75,14 @@ nodata:
|
||||
|
||||
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL;
|
||||
const char *family;
|
||||
sd_genl_family_t family;
|
||||
int r;
|
||||
|
||||
assert(genl);
|
||||
assert(ifindex > 0);
|
||||
assert(bssid);
|
||||
|
||||
r = sd_genl_message_new(genl, NL80211_GENL_NAME, NL80211_CMD_GET_STATION, &m);
|
||||
r = sd_genl_message_new(genl, SD_GENL_NL80211, NL80211_CMD_GET_STATION, &m);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to create generic netlink message: %m");
|
||||
|
||||
@ -107,11 +106,11 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to get information about wifi station: %m");
|
||||
|
||||
r = sd_genl_message_get_family_name(genl, reply, &family);
|
||||
r = sd_genl_message_get_family(genl, reply, &family);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine genl family: %m");
|
||||
if (!streq(family, NL80211_GENL_NAME)) {
|
||||
log_debug("Received message of unexpected genl family '%s', ignoring.", family);
|
||||
if (family != SD_GENL_NL80211) {
|
||||
log_debug("Received message of unexpected genl family %" PRIi64 ", ignoring.", family);
|
||||
goto nodata;
|
||||
}
|
||||
|
||||
|
||||
@ -31,15 +31,32 @@
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_netlink sd_netlink;
|
||||
typedef struct sd_genl_socket sd_genl_socket;
|
||||
typedef struct sd_netlink_message sd_netlink_message;
|
||||
typedef struct sd_netlink_slot sd_netlink_slot;
|
||||
|
||||
typedef enum sd_genl_family_t {
|
||||
SD_GENL_ERROR,
|
||||
SD_GENL_DONE,
|
||||
SD_GENL_ID_CTRL,
|
||||
SD_GENL_WIREGUARD,
|
||||
SD_GENL_FOU,
|
||||
SD_GENL_L2TP,
|
||||
SD_GENL_MACSEC,
|
||||
SD_GENL_NL80211,
|
||||
SD_GENL_BATADV,
|
||||
_SD_GENL_FAMILY_MAX,
|
||||
_SD_GENL_FAMILY_INVALID = -EINVAL,
|
||||
_SD_ENUM_FORCE_S64(GENL_FAMILY)
|
||||
} sd_genl_family_t;
|
||||
|
||||
/* callback */
|
||||
|
||||
typedef int (*sd_netlink_message_handler_t)(sd_netlink *nl, sd_netlink_message *m, void *userdata);
|
||||
typedef _sd_destroy_t sd_netlink_destroy_t;
|
||||
|
||||
/* bus */
|
||||
int sd_netlink_new_from_fd(sd_netlink **nl, int fd);
|
||||
int sd_netlink_new_from_netlink(sd_netlink **nl, int fd);
|
||||
int sd_netlink_open(sd_netlink **nl);
|
||||
int sd_netlink_open_fd(sd_netlink **nl, int fd);
|
||||
int sd_netlink_inc_rcvbuf(sd_netlink *nl, const size_t size);
|
||||
@ -69,7 +86,6 @@ int sd_netlink_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, uint16_t ma
|
||||
int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
|
||||
int sd_netlink_detach_event(sd_netlink *nl);
|
||||
|
||||
/* message */
|
||||
int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data);
|
||||
int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data);
|
||||
int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type);
|
||||
@ -113,7 +129,7 @@ int sd_netlink_message_exit_container(sd_netlink_message *m);
|
||||
int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type);
|
||||
int sd_netlink_message_cancel_array(sd_netlink_message *m);
|
||||
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *nl);
|
||||
int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl);
|
||||
|
||||
sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m);
|
||||
|
||||
@ -166,12 +182,12 @@ int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char
|
||||
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);
|
||||
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type);
|
||||
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int nh_family, unsigned char nh_protocol);
|
||||
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol);
|
||||
int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags);
|
||||
int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family);
|
||||
int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol);
|
||||
|
||||
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int nda_family);
|
||||
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
|
||||
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
|
||||
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
|
||||
int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family);
|
||||
@ -208,13 +224,13 @@ int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle);
|
||||
int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex);
|
||||
|
||||
/* nfnl */
|
||||
int sd_nfnl_socket_open(sd_netlink **ret);
|
||||
int sd_nfnl_socket_open(sd_netlink **nl);
|
||||
int sd_nfnl_message_batch_begin(sd_netlink *nfnl, sd_netlink_message **ret);
|
||||
int sd_nfnl_message_batch_end(sd_netlink *nfnl, sd_netlink_message **ret);
|
||||
int sd_nfnl_nft_message_del_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table);
|
||||
int sd_nfnl_nft_message_new_table(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table);
|
||||
int family, const char *table, uint16_t nl_flags);
|
||||
int sd_nfnl_nft_message_new_basechain(sd_netlink *nfnl, sd_netlink_message **ret,
|
||||
int family, const char *table, const char *chain,
|
||||
const char *type, uint8_t hook, int prio);
|
||||
@ -234,19 +250,13 @@ int sd_nfnl_nft_message_add_setelem(sd_netlink_message *m,
|
||||
int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m);
|
||||
|
||||
/* genl */
|
||||
int sd_genl_socket_open(sd_netlink **ret);
|
||||
int sd_genl_message_new(sd_netlink *genl, const char *family_name, uint8_t cmd, sd_netlink_message **ret);
|
||||
int sd_genl_message_get_family_name(sd_netlink *genl, sd_netlink_message *m, const char **ret);
|
||||
int sd_genl_message_get_command(sd_netlink *genl, sd_netlink_message *m, uint8_t *ret);
|
||||
int sd_genl_add_match(sd_netlink *nl, sd_netlink_slot **ret_slot, const char *family_name,
|
||||
const char *multicast_group_name, uint8_t command,
|
||||
sd_netlink_message_handler_t callback,
|
||||
sd_netlink_destroy_t destroy_callback,
|
||||
void *userdata, const char *description);
|
||||
int sd_genl_socket_open(sd_netlink **nl);
|
||||
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **ret);
|
||||
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *ret);
|
||||
|
||||
/* slot */
|
||||
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *slot);
|
||||
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *slot);
|
||||
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);
|
||||
sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl);
|
||||
|
||||
sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot);
|
||||
void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot);
|
||||
|
||||
@ -4,13 +4,9 @@
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "dropin.h"
|
||||
#include "errno-list.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
@ -18,14 +14,11 @@
|
||||
#include "missing_prctl.h"
|
||||
#include "mkdir.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "rm-rf.h"
|
||||
#if HAVE_SECCOMP
|
||||
#include "seccomp-util.h"
|
||||
#endif
|
||||
#include "service.h"
|
||||
#include "signal-util.h"
|
||||
#include "static-destruct.h"
|
||||
#include "stat-util.h"
|
||||
#include "tests.h"
|
||||
#include "unit.h"
|
||||
@ -33,11 +26,8 @@
|
||||
#include "util.h"
|
||||
#include "virt.h"
|
||||
|
||||
static char *user_runtime_unit_dir = NULL;
|
||||
static bool can_unshare;
|
||||
|
||||
STATIC_DESTRUCTOR_REGISTER(user_runtime_unit_dir, freep);
|
||||
|
||||
typedef void (*test_function_t)(Manager *m);
|
||||
|
||||
static int cld_dumped_to_killed(int code) {
|
||||
@ -89,15 +79,16 @@ static void check_main_result(const char *file, unsigned line, const char *func,
|
||||
exec_status_dump(&service->main_exec_status, stdout, "\t");
|
||||
|
||||
if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) {
|
||||
log_error("%s:%u:%s %s: can_unshare=%s: exit code %d, expected %d",
|
||||
file, line, func, unit->id, yes_no(can_unshare),
|
||||
log_error("%s:%u:%s %s: exit code %d, expected %d",
|
||||
file, line, func,
|
||||
unit->id,
|
||||
service->main_exec_status.code, code_expected);
|
||||
abort();
|
||||
}
|
||||
|
||||
if (service->main_exec_status.status != status_expected) {
|
||||
log_error("%s:%u:%s: %s: can_unshare=%s: exit status %d, expected %d",
|
||||
file, line, func, unit->id, yes_no(can_unshare),
|
||||
log_error("%s:%u:%s: %s: exit status %d, expected %d",
|
||||
file, line, func, unit->id,
|
||||
service->main_exec_status.status, status_expected);
|
||||
abort();
|
||||
}
|
||||
@ -115,8 +106,9 @@ static void check_service_result(const char *file, unsigned line, const char *fu
|
||||
service = SERVICE(unit);
|
||||
|
||||
if (service->result != result_expected) {
|
||||
log_error("%s:%u:%s: %s: can_unshare=%s: service end result %s, expected %s",
|
||||
file, line, func, unit->id, yes_no(can_unshare),
|
||||
log_error("%s:%u:%s: %s: service end result %s, expected %s",
|
||||
file, line, func,
|
||||
unit->id,
|
||||
service_result_to_string(service->result),
|
||||
service_result_to_string(result_expected));
|
||||
abort();
|
||||
@ -416,190 +408,6 @@ static void test_exec_inaccessiblepaths(Manager *m) {
|
||||
test(m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
|
||||
}
|
||||
|
||||
static int on_spawn_io(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
char **result = userdata;
|
||||
char buf[4096];
|
||||
ssize_t l;
|
||||
|
||||
assert(s);
|
||||
assert(fd >= 0);
|
||||
|
||||
l = read(fd, buf, sizeof(buf) - 1);
|
||||
if (l < 0) {
|
||||
if (errno == EAGAIN)
|
||||
goto reenable;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if (l == 0)
|
||||
return 0;
|
||||
|
||||
buf[l] = '\0';
|
||||
if (result)
|
||||
assert_se(strextend(result, buf));
|
||||
else
|
||||
log_error("ldd: %s", buf);
|
||||
|
||||
reenable:
|
||||
/* Re-enable the event source if we did not encounter EOF */
|
||||
assert_se(sd_event_source_set_enabled(s, SD_EVENT_ONESHOT) >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_spawn_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
|
||||
pid_t *pid = userdata;
|
||||
|
||||
assert(pid);
|
||||
|
||||
(void) kill(*pid, SIGKILL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int on_spawn_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||
int ret = -EIO;
|
||||
|
||||
assert(si);
|
||||
|
||||
if (si->si_code == CLD_EXITED)
|
||||
ret = si->si_status;
|
||||
|
||||
sd_event_exit(sd_event_source_get_event(s), ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int find_libraries(const char *exec, char ***ret) {
|
||||
_cleanup_(sd_event_unrefp) sd_event *e = NULL;
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *sigchld_source = NULL;
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *stdout_source = NULL;
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *stderr_source = NULL;
|
||||
_cleanup_close_pair_ int outpipe[2] = {-1, -1}, errpipe[2] = {-1, -1};
|
||||
_cleanup_strv_free_ char **libraries = NULL;
|
||||
_cleanup_free_ char *result = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert(exec);
|
||||
assert(ret);
|
||||
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGCHLD, -1) >= 0);
|
||||
|
||||
assert_se(pipe2(outpipe, O_NONBLOCK|O_CLOEXEC) == 0);
|
||||
assert_se(pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) == 0);
|
||||
|
||||
r = safe_fork("(spawn-ldd)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0) {
|
||||
if (rearrange_stdio(-1, outpipe[1], errpipe[1]) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
(void) close_all_fds(NULL, 0);
|
||||
|
||||
execlp("ldd", "ldd", exec, NULL);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
outpipe[1] = safe_close(outpipe[1]);
|
||||
errpipe[1] = safe_close(errpipe[1]);
|
||||
|
||||
assert_se(sd_event_new(&e) >= 0);
|
||||
|
||||
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_MONOTONIC,
|
||||
10 * USEC_PER_SEC, USEC_PER_SEC, on_spawn_timeout, &pid) >= 0);
|
||||
assert_se(sd_event_add_io(e, &stdout_source, outpipe[0], EPOLLIN, on_spawn_io, &result) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(stdout_source, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(sd_event_add_io(e, &stderr_source, errpipe[0], EPOLLIN, on_spawn_io, NULL) >= 0);
|
||||
assert_se(sd_event_source_set_enabled(stderr_source, SD_EVENT_ONESHOT) >= 0);
|
||||
assert_se(sd_event_add_child(e, &sigchld_source, pid, WEXITED, on_spawn_sigchld, NULL) >= 0);
|
||||
/* SIGCHLD should be processed after IO is complete */
|
||||
assert_se(sd_event_source_set_priority(sigchld_source, SD_EVENT_PRIORITY_NORMAL + 1) >= 0);
|
||||
|
||||
assert_se(sd_event_loop(e) >= 0);
|
||||
|
||||
_cleanup_strv_free_ char **v = NULL;
|
||||
assert_se(strv_split_newlines_full(&v, result, 0) >= 0);
|
||||
|
||||
char **q;
|
||||
STRV_FOREACH(q, v) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
const char *p = *q;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (path_is_absolute(word)) {
|
||||
assert_se(strv_consume(&libraries, TAKE_PTR(word)) >= 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
word = mfree(word);
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (!streq_ptr(word, "=>"))
|
||||
continue;
|
||||
|
||||
word = mfree(word);
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
assert_se(r >= 0);
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
if (path_is_absolute(word)) {
|
||||
assert_se(strv_consume(&libraries, TAKE_PTR(word)) >= 0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(libraries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_exec_mount_apivfs(Manager *m) {
|
||||
_cleanup_free_ char *fullpath_touch = NULL, *fullpath_test = NULL, *data = NULL;
|
||||
_cleanup_strv_free_ char **libraries = NULL, **libraries_test = NULL;
|
||||
int r;
|
||||
|
||||
assert(user_runtime_unit_dir);
|
||||
|
||||
r = find_executable("touch", &fullpath_touch);
|
||||
if (r < 0) {
|
||||
log_notice_errno(r, "Skipping %s, could not find 'touch' command: %m", __func__);
|
||||
return;
|
||||
}
|
||||
r = find_executable("test", &fullpath_test);
|
||||
if (r < 0) {
|
||||
log_notice_errno(r, "Skipping %s, could not find 'test' command: %m", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(find_libraries(fullpath_touch, &libraries) >= 0);
|
||||
assert_se(find_libraries(fullpath_test, &libraries_test) >= 0);
|
||||
assert_se(strv_extend_strv(&libraries, libraries_test, true) >= 0);
|
||||
|
||||
assert_se(strextend(&data, "[Service]\n"));
|
||||
assert_se(strextend(&data, "ExecStart=", fullpath_touch, " /aaa\n"));
|
||||
assert_se(strextend(&data, "ExecStart=", fullpath_test, " -f /aaa\n"));
|
||||
assert_se(strextend(&data, "BindReadOnlyPaths=", fullpath_touch, "\n"));
|
||||
assert_se(strextend(&data, "BindReadOnlyPaths=", fullpath_test, "\n"));
|
||||
|
||||
char **p;
|
||||
STRV_FOREACH(p, libraries)
|
||||
assert_se(strextend(&data, "BindReadOnlyPaths=", *p, "\n"));
|
||||
|
||||
assert_se(write_drop_in(user_runtime_unit_dir, "exec-mount-apivfs-no.service", 10, "bind-mount", data) >= 0);
|
||||
|
||||
assert_se(mkdir_p("/tmp/test-exec-mount-apivfs-no/root", 0755) >= 0);
|
||||
|
||||
test(m, "exec-mount-apivfs-no.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
|
||||
|
||||
(void) rm_rf("/tmp/test-exec-mount-apivfs-no/root", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||
}
|
||||
|
||||
static void test_exec_noexecpaths(Manager *m) {
|
||||
|
||||
test(m, "exec-noexecpaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
|
||||
@ -1063,7 +871,6 @@ int main(int argc, char *argv[]) {
|
||||
entry(test_exec_ignoresigpipe),
|
||||
entry(test_exec_inaccessiblepaths),
|
||||
entry(test_exec_ioschedulingclass),
|
||||
entry(test_exec_mount_apivfs),
|
||||
entry(test_exec_noexecpaths),
|
||||
entry(test_exec_oomscoreadjust),
|
||||
entry(test_exec_passenvironment),
|
||||
@ -1124,12 +931,10 @@ int main(int argc, char *argv[]) {
|
||||
if (r == -ENOMEDIUM)
|
||||
return log_tests_skipped("cgroupfs not available");
|
||||
|
||||
_cleanup_free_ char *unit_dir = NULL, *unit_paths = NULL;
|
||||
_cleanup_free_ char *unit_dir = NULL;
|
||||
assert_se(get_testdata_dir("test-execute/", &unit_dir) >= 0);
|
||||
assert_se(set_unit_path(unit_dir) >= 0);
|
||||
assert_se(runtime_dir = setup_fake_runtime_dir());
|
||||
assert_se(user_runtime_unit_dir = path_join(runtime_dir, "systemd/user"));
|
||||
assert_se(unit_paths = strjoin(unit_dir, ":", user_runtime_unit_dir));
|
||||
assert_se(set_unit_path(unit_paths) >= 0);
|
||||
|
||||
/* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
|
||||
* cases, otherwise (and if they are present in the environment),
|
||||
|
||||
@ -142,8 +142,6 @@ int link_load_one(LinkConfigContext *ctx, const char *filename) {
|
||||
.tx_flow_control = -1,
|
||||
.autoneg_flow_control = -1,
|
||||
.txqueuelen = UINT32_MAX,
|
||||
.coalesce.use_adaptive_rx_coalesce = -1,
|
||||
.coalesce.use_adaptive_tx_coalesce = -1,
|
||||
};
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(link->features); i++)
|
||||
|
||||
@ -1 +0,0 @@
|
||||
../TEST-01-BASIC/Makefile
|
||||
@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/17433"
|
||||
|
||||
# shellcheck source=test/test-functions
|
||||
. "${TEST_BASE_DIR:?}/test-functions"
|
||||
|
||||
do_test "$@"
|
||||
@ -33,8 +33,6 @@ if install_tests
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-52.units',
|
||||
install_dir : testdata_dir)
|
||||
install_subdir('testsuite-63.units',
|
||||
install_dir : testdata_dir)
|
||||
|
||||
testsuite08_dir = testdata_dir + '/testsuite-08.units'
|
||||
install_data('testsuite-08.units/-.mount',
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
[Unit]
|
||||
Description=Test for find_executable() with MountAPIVFS=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
|
||||
MountAPIVFS=false
|
||||
PrivateDevices=false
|
||||
PrivateMounts=true
|
||||
PrivateTmp=false
|
||||
PrivateUsers=false
|
||||
ProtectControlGroups=false
|
||||
ProtectKernelModules=false
|
||||
ProtectKernelTunables=false
|
||||
RootDirectory=/tmp/test-exec-mount-apivfs-no/root
|
||||
@ -148,7 +148,6 @@ BASICTOOLS=(
|
||||
head
|
||||
ionice
|
||||
ip
|
||||
ldd
|
||||
ln
|
||||
loadkeys
|
||||
login
|
||||
|
||||
@ -1155,8 +1155,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
f.write('[MACVTAP]\nMode=' + mode)
|
||||
start_networkd()
|
||||
|
||||
self.wait_online(['macvtap99:degraded',
|
||||
'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
|
||||
self.wait_online(['macvtap99:degraded', 'test1:degraded'])
|
||||
|
||||
output = check_output('ip -d link show macvtap99')
|
||||
print(output)
|
||||
@ -1173,8 +1172,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
f.write('[MACVLAN]\nMode=' + mode)
|
||||
start_networkd()
|
||||
|
||||
self.wait_online(['macvlan99:degraded',
|
||||
'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
|
||||
self.wait_online(['macvlan99:degraded', 'test1:degraded'])
|
||||
|
||||
output = check_output('ip -d link show test1')
|
||||
print(output)
|
||||
@ -1193,8 +1191,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
||||
self.assertEqual(rc, 0)
|
||||
time.sleep(1)
|
||||
|
||||
self.wait_online(['macvlan99:degraded',
|
||||
'test1:carrier' if mode == 'passthru' else 'test1:degraded'])
|
||||
self.wait_online(['macvlan99:degraded', 'test1:degraded'])
|
||||
|
||||
output = check_output('ip -d link show test1')
|
||||
print(output)
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
[Unit]
|
||||
Requires=test10.socket
|
||||
ConditionPathExistsGlob=/tmp/nonexistent
|
||||
# Make sure we hit the socket trigger limit in the test and not the service start limit.
|
||||
StartLimitInterval=1000
|
||||
StartLimitBurst=1000
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
[Path]
|
||||
PathExists=/tmp/test63
|
||||
@ -1,5 +0,0 @@
|
||||
[Unit]
|
||||
ConditionPathExists=!/tmp/nonexistent
|
||||
|
||||
[Service]
|
||||
ExecStart=true
|
||||
@ -1,16 +0,0 @@
|
||||
[Unit]
|
||||
Description=TEST-63-ISSUE-17433
|
||||
|
||||
[Service]
|
||||
ExecStartPre=rm -f /failed /testok
|
||||
Type=oneshot
|
||||
ExecStart=rm -f /tmp/nonexistent
|
||||
ExecStart=systemctl start test63.path
|
||||
ExecStart=touch /tmp/test63
|
||||
# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
||||
ExecStart=sleep 2
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
|
||||
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
|
||||
ExecStart=sh -x -c 'echo OK >/testok'
|
||||
Loading…
x
Reference in New Issue
Block a user