Compare commits
35 Commits
d9ceeb9fe7
...
e40b4caa1f
Author | SHA1 | Date |
---|---|---|
Thomas Haller | e40b4caa1f | |
Benjamin Dahlhoff | cb180b09fa | |
Yu Watanabe | 3771024c24 | |
Lennart Poettering | da7667518b | |
Lennart Poettering | 90d81ee966 | |
Lennart Poettering | c84d9b3b71 | |
Lennart Poettering | 3b5cd25f4d | |
Lennart Poettering | 32b7cdc14c | |
Yu Watanabe | 7a2f6fb6f1 | |
Yu Watanabe | 6934ace05d | |
Yu Watanabe | 511070ee95 | |
Yu Watanabe | 572b21d96c | |
Yu Watanabe | a5053a158b | |
Yu Watanabe | 4252696aec | |
Yu Watanabe | d08d92d5ee | |
Yu Watanabe | 6d725977c4 | |
Yu Watanabe | 8f3c185966 | |
Zbigniew Jędrzejewski-Szmek | 0181314861 | |
Zbigniew Jędrzejewski-Szmek | 35b9eb0a72 | |
Zbigniew Jędrzejewski-Szmek | a97abb30e7 | |
Zbigniew Jędrzejewski-Szmek | f2d9213fee | |
Zbigniew Jędrzejewski-Szmek | e8af3bfd63 | |
Yu Watanabe | ffeb16f5d8 | |
Yu Watanabe | d3678e3a0b | |
Zbigniew Jędrzejewski-Szmek | 6b2a8b80b4 | |
Zbigniew Jędrzejewski-Szmek | ba5450f411 | |
Zbigniew Jędrzejewski-Szmek | 1163a2e98a | |
Zbigniew Jędrzejewski-Szmek | 14bb274d3f | |
Zbigniew Jędrzejewski-Szmek | 3d92aa4596 | |
Zbigniew Jędrzejewski-Szmek | 46c41478c9 | |
Zbigniew Jędrzejewski-Szmek | 607ebf2bd2 | |
Zbigniew Jędrzejewski-Szmek | b50a3a1565 | |
Zbigniew Jędrzejewski-Szmek | 1fac34b941 | |
Zbigniew Jędrzejewski-Szmek | 074cdb953b | |
Zbigniew Jędrzejewski-Szmek | 9fe6f5cc16 |
|
@ -8,7 +8,7 @@ about: A report of an error in a recent systemd version
|
|||
> ...
|
||||
|
||||
<!-- **NOTE:** Do not submit bug reports about anything but the two most recently released systemd versions upstream! -->
|
||||
<!-- For older version please use distribution trackers (see https://github.com/systemd/systemd/blob/master/docs/CONTRIBUTING.md#filing-issues). -->
|
||||
<!-- For older version please use distribution trackers (see https://systemd.io/CONTRIBUTING#filing-issues). -->
|
||||
|
||||
**Used distribution**
|
||||
> …
|
||||
|
|
2
TODO
2
TODO
|
@ -234,7 +234,7 @@ Features:
|
|||
1. add resume_offset support to the resume code (i.e. support swap files
|
||||
properly)
|
||||
2. check if swap is on weird storage and refuse if so
|
||||
3. add autodetection of hibernation images
|
||||
3. add auto-detection of hibernation images
|
||||
|
||||
* cgroups: use inotify to get notified when somebody else modifies cgroups
|
||||
owned by us, then log a friendly warning.
|
||||
|
|
|
@ -606,6 +606,7 @@ sensor:modalias:acpi:BMA250*:dmi:*:bvrTREK.G.WI71C.JGBMRBA*:*:svnInsyde:pnST7041
|
|||
sensor:modalias:acpi:BMA250*:dmi:*:bvrTREK.G.WI71C.JGBMRBA*:*:svnTrekStor:pnSurfTabwintron7.0ST70416-6:*
|
||||
ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
|
||||
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR*:pnPrimetabS11B:*
|
||||
sensor:modalias:acpi:KIOX000A*:dmi:*:svnTREKSTOR:pnPrimetabT13B:*
|
||||
sensor:modalias:acpi:BOSC0200*:dmi:*:svnTrekStor*:pnSurfTabtwin11.6:*
|
||||
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
root, <filename>/home/</filename>, <filename>/srv/</filename>, the EFI System Partition, the Extended
|
||||
Boot Loader Partition and swap partitions and creates mount and swap units for them, based on the
|
||||
partition type GUIDs of GUID partition tables (GPT), see <ulink
|
||||
url="https://uefi.org/specifications">UEFI Specification</ulink>, chapter 5. It implements the <ulink
|
||||
url="https://uefi.org/specifications">UEFI Specification</ulink>, chapter 5. It implements the <ulink
|
||||
url="https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/">Discoverable Partitions
|
||||
Specification</ulink>. Note that this generator has no effect on non-GPT systems, and on specific mount
|
||||
points that are directories already containing files. Also, on systems where the units are explicitly
|
||||
|
@ -44,18 +44,21 @@
|
|||
units this generator creates are overridden, but additional implicit dependencies might be
|
||||
created.</para>
|
||||
|
||||
<para>This generator will only look for root partitions on the
|
||||
same physical disk the EFI System Partition (ESP) is located on.
|
||||
It will only look for the other partitions on the same physical
|
||||
disk the root file system is located on. These partitions will not
|
||||
be searched for on systems where the root file system is distributed
|
||||
on multiple disks, for example via btrfs RAID.</para>
|
||||
<para>This generator will only look for the root partition on the same physical disk the EFI System
|
||||
Partition (ESP) is located on. Note that support from the boot loader is required: EFI variable
|
||||
<varname>LoaderDevicePartUUID-4a67b082-0a4c-41cf-b6c7-440b29bb8c4f</varname> is used to determine from
|
||||
which partition, and hence the disk from which the system was booted. If the boot loader does not set
|
||||
this variable, this generator will not be able to autodetect the root partition.</para>
|
||||
|
||||
<para><filename>systemd-gpt-auto-generator</filename> is useful
|
||||
for centralizing file system configuration in the partition table
|
||||
and making configuration in <filename>/etc/fstab</filename> unnecessary.
|
||||
<para>Similarly, this generator will only look for the other partitions on the same physical disk as the
|
||||
root partition. In this case, boot loader support is not required. These partitions will not be searched
|
||||
for on systems where the root file system is distributed on multiple disks, for example via btrfs RAID.
|
||||
</para>
|
||||
|
||||
<para><filename>systemd-gpt-auto-generator</filename> is useful for centralizing file system
|
||||
configuration in the partition table and making configuration in <filename>/etc/fstab</filename> or on
|
||||
the kernel command line unnecessary.</para>
|
||||
|
||||
<para>This generator looks for the partitions based on their
|
||||
partition type GUID. The following partition type GUIDs are
|
||||
identified:</para>
|
||||
|
|
|
@ -356,6 +356,14 @@
|
|||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>AlternativeName=</varname></term>
|
||||
<listitem>
|
||||
<para>The alternative interface name to use. This option can be specified multiple times.
|
||||
If the empty string is assigned to this option, the list is reset, and all prior assignments
|
||||
have no effect.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>MTUBytes=</varname></term>
|
||||
<listitem>
|
||||
|
|
|
@ -132,10 +132,9 @@
|
|||
<varlistentry>
|
||||
<term><varname>Name=</varname></term>
|
||||
<listitem>
|
||||
<para>A whitespace-separated list of shell-style globs
|
||||
matching the device name, as exposed by the udev property
|
||||
<literal>INTERFACE</literal>. If the list is prefixed
|
||||
with a "!", the test is inverted.</para>
|
||||
<para>A whitespace-separated list of shell-style globs matching the device name, as exposed
|
||||
by the udev property <literal>INTERFACE</literal>, or device's alternative names. If the
|
||||
list is prefixed with a "!", the test is inverted.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
|
|
@ -90,13 +90,14 @@ int efi_get_variable(
|
|||
n = read(fd, buf, (size_t) st.st_size - 4);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
if (n != st.st_size - 4)
|
||||
return -EIO;
|
||||
assert(n <= st.st_size - 4);
|
||||
|
||||
/* Always NUL terminate (2 bytes, to protect UTF-16) */
|
||||
((char*) buf)[st.st_size - 4] = 0;
|
||||
((char*) buf)[st.st_size - 4 + 1] = 0;
|
||||
}
|
||||
((char*) buf)[n - 4] = 0;
|
||||
((char*) buf)[n - 4 + 1] = 0;
|
||||
} else
|
||||
/* Assume that the reported size is accurate */
|
||||
n = st.st_size - 4;
|
||||
|
||||
/* Note that efivarfs interestingly doesn't require ftruncate() to update an existing EFI variable
|
||||
* with a smaller value. */
|
||||
|
@ -108,7 +109,7 @@ int efi_get_variable(
|
|||
*ret_value = TAKE_PTR(buf);
|
||||
|
||||
if (ret_size)
|
||||
*ret_size = (size_t) st.st_size - 4;
|
||||
*ret_size = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -270,6 +270,7 @@ struct btrfs_ioctl_fs_info_args {
|
|||
#define BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA (1ULL << 8)
|
||||
#define BTRFS_FEATURE_INCOMPAT_NO_HOLES (1ULL << 9)
|
||||
#define BTRFS_FEATURE_INCOMPAT_METADATA_UUID (1ULL << 10)
|
||||
#define BTRFS_FEATURE_INCOMPAT_RAID1C34 (1ULL << 11)
|
||||
|
||||
struct btrfs_ioctl_feature_flags {
|
||||
__u64 compat_flags;
|
||||
|
@ -665,7 +666,12 @@ struct btrfs_ioctl_get_dev_stats {
|
|||
/* out values: */
|
||||
__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
|
||||
|
||||
__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
|
||||
/*
|
||||
* This pads the struct to 1032 bytes. It was originally meant to pad to
|
||||
* 1024 bytes, but when adding the flags field, the padding calculation
|
||||
* was not adjusted.
|
||||
*/
|
||||
__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX];
|
||||
};
|
||||
|
||||
#define BTRFS_QUOTA_CTL_ENABLE 1
|
||||
|
@ -826,7 +832,9 @@ enum btrfs_err_code {
|
|||
BTRFS_ERROR_DEV_TGT_REPLACE,
|
||||
BTRFS_ERROR_DEV_MISSING_NOT_FOUND,
|
||||
BTRFS_ERROR_DEV_ONLY_WRITABLE,
|
||||
BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS
|
||||
BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS,
|
||||
BTRFS_ERROR_DEV_RAID1C3_MIN_NOT_MET,
|
||||
BTRFS_ERROR_DEV_RAID1C4_MIN_NOT_MET,
|
||||
};
|
||||
|
||||
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
|
||||
|
@ -917,10 +925,8 @@ enum btrfs_err_code {
|
|||
#define BTRFS_IOC_QUOTA_RESCAN_STATUS _IOR(BTRFS_IOCTL_MAGIC, 45, \
|
||||
struct btrfs_ioctl_quota_rescan_args)
|
||||
#define BTRFS_IOC_QUOTA_RESCAN_WAIT _IO(BTRFS_IOCTL_MAGIC, 46)
|
||||
#define BTRFS_IOC_GET_FSLABEL _IOR(BTRFS_IOCTL_MAGIC, 49, \
|
||||
char[BTRFS_LABEL_SIZE])
|
||||
#define BTRFS_IOC_SET_FSLABEL _IOW(BTRFS_IOCTL_MAGIC, 50, \
|
||||
char[BTRFS_LABEL_SIZE])
|
||||
#define BTRFS_IOC_GET_FSLABEL FS_IOC_GETFSLABEL
|
||||
#define BTRFS_IOC_SET_FSLABEL FS_IOC_SETFSLABEL
|
||||
#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
|
||||
struct btrfs_ioctl_get_dev_stats)
|
||||
#define BTRFS_IOC_DEV_REPLACE _IOWR(BTRFS_IOCTL_MAGIC, 53, \
|
||||
|
|
|
@ -300,7 +300,12 @@
|
|||
#define BTRFS_CSUM_SIZE 32
|
||||
|
||||
/* csum types */
|
||||
#define BTRFS_CSUM_TYPE_CRC32 0
|
||||
enum btrfs_csum_type {
|
||||
BTRFS_CSUM_TYPE_CRC32 = 0,
|
||||
BTRFS_CSUM_TYPE_XXHASH = 1,
|
||||
BTRFS_CSUM_TYPE_SHA256 = 2,
|
||||
BTRFS_CSUM_TYPE_BLAKE2 = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* flags definitions for directory entry item type
|
||||
|
@ -735,10 +740,12 @@ struct btrfs_balance_item {
|
|||
__le64 unused[4];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
#define BTRFS_FILE_EXTENT_INLINE 0
|
||||
#define BTRFS_FILE_EXTENT_REG 1
|
||||
#define BTRFS_FILE_EXTENT_PREALLOC 2
|
||||
#define BTRFS_FILE_EXTENT_TYPES 2
|
||||
enum {
|
||||
BTRFS_FILE_EXTENT_INLINE = 0,
|
||||
BTRFS_FILE_EXTENT_REG = 1,
|
||||
BTRFS_FILE_EXTENT_PREALLOC = 2,
|
||||
BTRFS_NR_FILE_EXTENT_TYPES = 3,
|
||||
};
|
||||
|
||||
struct btrfs_file_extent_item {
|
||||
/*
|
||||
|
@ -806,11 +813,6 @@ struct btrfs_dev_stats_item {
|
|||
|
||||
#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_ALWAYS 0
|
||||
#define BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_AVOID 1
|
||||
#define BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED 0
|
||||
#define BTRFS_DEV_REPLACE_ITEM_STATE_STARTED 1
|
||||
#define BTRFS_DEV_REPLACE_ITEM_STATE_SUSPENDED 2
|
||||
#define BTRFS_DEV_REPLACE_ITEM_STATE_FINISHED 3
|
||||
#define BTRFS_DEV_REPLACE_ITEM_STATE_CANCELED 4
|
||||
|
||||
struct btrfs_dev_replace_item {
|
||||
/*
|
||||
|
@ -839,6 +841,8 @@ struct btrfs_dev_replace_item {
|
|||
#define BTRFS_BLOCK_GROUP_RAID10 (1ULL << 6)
|
||||
#define BTRFS_BLOCK_GROUP_RAID5 (1ULL << 7)
|
||||
#define BTRFS_BLOCK_GROUP_RAID6 (1ULL << 8)
|
||||
#define BTRFS_BLOCK_GROUP_RAID1C3 (1ULL << 9)
|
||||
#define BTRFS_BLOCK_GROUP_RAID1C4 (1ULL << 10)
|
||||
#define BTRFS_BLOCK_GROUP_RESERVED (BTRFS_AVAIL_ALLOC_BIT_SINGLE | \
|
||||
BTRFS_SPACE_INFO_GLOBAL_RSV)
|
||||
|
||||
|
@ -850,6 +854,8 @@ enum btrfs_raid_types {
|
|||
BTRFS_RAID_SINGLE,
|
||||
BTRFS_RAID_RAID5,
|
||||
BTRFS_RAID_RAID6,
|
||||
BTRFS_RAID_RAID1C3,
|
||||
BTRFS_RAID_RAID1C4,
|
||||
BTRFS_NR_RAID_TYPES
|
||||
};
|
||||
|
||||
|
@ -859,6 +865,8 @@ enum btrfs_raid_types {
|
|||
|
||||
#define BTRFS_BLOCK_GROUP_PROFILE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \
|
||||
BTRFS_BLOCK_GROUP_RAID1 | \
|
||||
BTRFS_BLOCK_GROUP_RAID1C3 | \
|
||||
BTRFS_BLOCK_GROUP_RAID1C4 | \
|
||||
BTRFS_BLOCK_GROUP_RAID5 | \
|
||||
BTRFS_BLOCK_GROUP_RAID6 | \
|
||||
BTRFS_BLOCK_GROUP_DUP | \
|
||||
|
@ -866,6 +874,10 @@ enum btrfs_raid_types {
|
|||
#define BTRFS_BLOCK_GROUP_RAID56_MASK (BTRFS_BLOCK_GROUP_RAID5 | \
|
||||
BTRFS_BLOCK_GROUP_RAID6)
|
||||
|
||||
#define BTRFS_BLOCK_GROUP_RAID1_MASK (BTRFS_BLOCK_GROUP_RAID1 | \
|
||||
BTRFS_BLOCK_GROUP_RAID1C3 | \
|
||||
BTRFS_BLOCK_GROUP_RAID1C4)
|
||||
|
||||
/*
|
||||
* We need a bit for restriper to be able to tell when chunks of type
|
||||
* SINGLE are available. This "extended" profile format is used in
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
#ifndef _UAPI_CAN_VXCAN_H
|
||||
#define _UAPI_CAN_VXCAN_H
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define IFNAMSIZ 16
|
||||
#endif /* __UAPI_DEF_IF_IFNAMSIZ */
|
||||
#define IFALIASZ 256
|
||||
#define ALTIFNAMSIZ 128
|
||||
#include <linux/hdlc/ioctl.h>
|
||||
|
||||
/* For glibc compatibility. An empty enum does not compile. */
|
||||
|
|
|
@ -237,6 +237,7 @@ struct br_mdb_entry {
|
|||
#define MDB_PERMANENT 1
|
||||
__u8 state;
|
||||
#define MDB_FLAGS_OFFLOAD (1 << 0)
|
||||
#define MDB_FLAGS_FAST_LEAVE (1 << 1)
|
||||
__u8 flags;
|
||||
__u16 vid;
|
||||
struct {
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
|
||||
#define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */
|
||||
#define ETH_P_TIPC 0x88CA /* TIPC */
|
||||
#define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */
|
||||
#define ETH_P_MACSEC 0x88E5 /* 802.1ae MACsec */
|
||||
#define ETH_P_8021AH 0x88E7 /* 802.1ah Backbone Service Tag */
|
||||
#define ETH_P_MVRP 0x88F5 /* 802.1Q MVRP */
|
||||
|
|
|
@ -167,6 +167,8 @@ enum {
|
|||
IFLA_NEW_IFINDEX,
|
||||
IFLA_MIN_MTU,
|
||||
IFLA_MAX_MTU,
|
||||
IFLA_PROP_LIST,
|
||||
IFLA_ALT_IFNAME, /* Alternative ifname */
|
||||
__IFLA_MAX
|
||||
};
|
||||
|
||||
|
@ -636,6 +638,7 @@ enum {
|
|||
IFLA_BOND_AD_USER_PORT_KEY,
|
||||
IFLA_BOND_AD_ACTOR_SYSTEM,
|
||||
IFLA_BOND_TLB_DYNAMIC_LB,
|
||||
IFLA_BOND_PEER_NOTIF_DELAY,
|
||||
__IFLA_BOND_MAX,
|
||||
};
|
||||
|
||||
|
@ -694,6 +697,7 @@ enum {
|
|||
IFLA_VF_IB_NODE_GUID, /* VF Infiniband node GUID */
|
||||
IFLA_VF_IB_PORT_GUID, /* VF Infiniband port GUID */
|
||||
IFLA_VF_VLAN_LIST, /* nested list of vlans, option for QinQ */
|
||||
IFLA_VF_BROADCAST, /* VF broadcast */
|
||||
__IFLA_VF_MAX,
|
||||
};
|
||||
|
||||
|
@ -704,6 +708,10 @@ struct ifla_vf_mac {
|
|||
__u8 mac[32]; /* MAX_ADDR_LEN */
|
||||
};
|
||||
|
||||
struct ifla_vf_broadcast {
|
||||
__u8 broadcast[32];
|
||||
};
|
||||
|
||||
struct ifla_vf_vlan {
|
||||
__u32 vf;
|
||||
__u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
#ifndef _LINUX_NEXTHOP_H
|
||||
#define _LINUX_NEXTHOP_H
|
||||
#ifndef _UAPI_LINUX_NEXTHOP_H
|
||||
#define _UAPI_LINUX_NEXTHOP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct nhmsg {
|
||||
unsigned char nh_family;
|
||||
unsigned char nh_scope; /* return only */
|
||||
unsigned char nh_protocol; /* Routing protocol that installed nh */
|
||||
unsigned char resvd;
|
||||
unsigned int nh_flags; /* RTNH_F flags */
|
||||
unsigned char nh_family;
|
||||
unsigned char nh_scope; /* return only */
|
||||
unsigned char nh_protocol; /* Routing protocol that installed nh */
|
||||
unsigned char resvd;
|
||||
unsigned int nh_flags; /* RTNH_F flags */
|
||||
};
|
||||
|
||||
/* entry in a nexthop group */
|
||||
struct nexthop_grp {
|
||||
__u32 id; /* nexthop id - must exist */
|
||||
__u8 weight; /* weight of this nexthop */
|
||||
__u8 resvd1;
|
||||
__u16 resvd2;
|
||||
__u32 id; /* nexthop id - must exist */
|
||||
__u8 weight; /* weight of this nexthop */
|
||||
__u8 resvd1;
|
||||
__u16 resvd2;
|
||||
};
|
||||
|
||||
enum {
|
||||
NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */
|
||||
__NEXTHOP_GRP_TYPE_MAX,
|
||||
NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */
|
||||
__NEXTHOP_GRP_TYPE_MAX,
|
||||
};
|
||||
|
||||
#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1)
|
||||
|
||||
enum {
|
||||
NHA_UNSPEC,
|
||||
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */
|
||||
NHA_UNSPEC,
|
||||
NHA_ID, /* u32; id for nexthop. id == 0 means auto-assign */
|
||||
|
||||
NHA_GROUP, /* array of nexthop_grp */
|
||||
NHA_GROUP_TYPE, /* u16 one of NEXTHOP_GRP_TYPE */
|
||||
/* if NHA_GROUP attribute is added, no other attributes can be set */
|
||||
NHA_GROUP, /* array of nexthop_grp */
|
||||
NHA_GROUP_TYPE, /* u16 one of NEXTHOP_GRP_TYPE */
|
||||
/* if NHA_GROUP attribute is added, no other attributes can be set */
|
||||
|
||||
NHA_BLACKHOLE, /* flag; nexthop used to blackhole packets */
|
||||
/* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */
|
||||
NHA_BLACKHOLE, /* flag; nexthop used to blackhole packets */
|
||||
/* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */
|
||||
|
||||
NHA_OIF, /* u32; nexthop device */
|
||||
NHA_GATEWAY, /* be32 (IPv4) or in6_addr (IPv6) gw address */
|
||||
NHA_ENCAP_TYPE, /* u16; lwt encap type */
|
||||
NHA_ENCAP, /* lwt encap data */
|
||||
NHA_OIF, /* u32; nexthop device */
|
||||
NHA_GATEWAY, /* be32 (IPv4) or in6_addr (IPv6) gw address */
|
||||
NHA_ENCAP_TYPE, /* u16; lwt encap type */
|
||||
NHA_ENCAP, /* lwt encap data */
|
||||
|
||||
/* NHA_OIF can be appended to dump request to return only
|
||||
* nexthops using given device
|
||||
*/
|
||||
NHA_GROUPS, /* flag; only return nexthop groups in dump */
|
||||
NHA_MASTER, /* u32; only return nexthops with given master dev */
|
||||
/* NHA_OIF can be appended to dump request to return only
|
||||
* nexthops using given device
|
||||
*/
|
||||
NHA_GROUPS, /* flag; only return nexthop groups in dump */
|
||||
NHA_MASTER, /* u32; only return nexthops with given master dev */
|
||||
|
||||
__NHA_MAX,
|
||||
__NHA_MAX,
|
||||
};
|
||||
|
||||
#define NHA_MAX (__NHA_MAX - 1)
|
||||
#define NHA_MAX (__NHA_MAX - 1)
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -157,13 +157,20 @@ enum {
|
|||
RTM_GETCHAIN,
|
||||
#define RTM_GETCHAIN RTM_GETCHAIN
|
||||
|
||||
RTM_NEWNEXTHOP = 104,
|
||||
RTM_NEWNEXTHOP = 104,
|
||||
#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP
|
||||
RTM_DELNEXTHOP,
|
||||
RTM_DELNEXTHOP,
|
||||
#define RTM_DELNEXTHOP RTM_DELNEXTHOP
|
||||
RTM_GETNEXTHOP,
|
||||
RTM_GETNEXTHOP,
|
||||
#define RTM_GETNEXTHOP RTM_GETNEXTHOP
|
||||
|
||||
RTM_NEWLINKPROP = 108,
|
||||
#define RTM_NEWLINKPROP RTM_NEWLINKPROP
|
||||
RTM_DELLINKPROP,
|
||||
#define RTM_DELLINKPROP RTM_DELLINKPROP
|
||||
RTM_GETLINKPROP,
|
||||
#define RTM_GETLINKPROP RTM_GETLINKPROP
|
||||
|
||||
__RTM_MAX,
|
||||
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
|
||||
};
|
||||
|
@ -172,7 +179,7 @@ enum {
|
|||
#define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2)
|
||||
#define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2)
|
||||
|
||||
/*
|
||||
/*
|
||||
Generic structure for encapsulation of optional route information.
|
||||
It is reminiscent of sockaddr, but with sa_family replaced
|
||||
with attribute type.
|
||||
|
@ -212,7 +219,7 @@ struct rtmsg {
|
|||
|
||||
unsigned char rtm_table; /* Routing table id */
|
||||
unsigned char rtm_protocol; /* Routing protocol; see below */
|
||||
unsigned char rtm_scope; /* See below */
|
||||
unsigned char rtm_scope; /* See below */
|
||||
unsigned char rtm_type; /* See below */
|
||||
|
||||
unsigned rtm_flags;
|
||||
|
@ -349,7 +356,7 @@ enum rtattr_type_t {
|
|||
RTA_IP_PROTO,
|
||||
RTA_SPORT,
|
||||
RTA_DPORT,
|
||||
RTA_NH_ID,
|
||||
RTA_NH_ID,
|
||||
__RTA_MAX
|
||||
};
|
||||
|
||||
|
@ -523,7 +530,7 @@ struct ifinfomsg {
|
|||
};
|
||||
|
||||
/********************************************************************
|
||||
* prefix information
|
||||
* prefix information
|
||||
****/
|
||||
|
||||
struct prefixmsg {
|
||||
|
@ -537,7 +544,7 @@ struct prefixmsg {
|
|||
unsigned char prefix_pad3;
|
||||
};
|
||||
|
||||
enum
|
||||
enum
|
||||
{
|
||||
PREFIX_UNSPEC,
|
||||
PREFIX_ADDRESS,
|
||||
|
@ -712,7 +719,7 @@ enum rtnetlink_groups {
|
|||
#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
|
||||
RTNLGRP_IPV6_MROUTE_R,
|
||||
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
|
||||
RTNLGRP_NEXTHOP,
|
||||
RTNLGRP_NEXTHOP,
|
||||
#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
|
||||
__RTNLGRP_MAX
|
||||
};
|
||||
|
|
|
@ -18,30 +18,30 @@
|
|||
* one but not both of:
|
||||
*
|
||||
* WGDEVICE_A_IFINDEX: NLA_U32
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1
|
||||
*
|
||||
* The kernel will then return several messages (NLM_F_MULTI) containing the
|
||||
* following tree of nested items:
|
||||
*
|
||||
* WGDEVICE_A_IFINDEX: NLA_U32
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
|
||||
* WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN
|
||||
* WGDEVICE_A_PUBLIC_KEY: len WG_KEY_LEN
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1
|
||||
* WGDEVICE_A_PRIVATE_KEY: NLA_EXACT_LEN, len WG_KEY_LEN
|
||||
* WGDEVICE_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN
|
||||
* WGDEVICE_A_LISTEN_PORT: NLA_U16
|
||||
* WGDEVICE_A_FWMARK: NLA_U32
|
||||
* WGDEVICE_A_PEERS: NLA_NESTED
|
||||
* 0: NLA_NESTED
|
||||
* WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN
|
||||
* WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN
|
||||
* WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6
|
||||
* WGPEER_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN
|
||||
* WGPEER_A_PRESHARED_KEY: NLA_EXACT_LEN, len WG_KEY_LEN
|
||||
* WGPEER_A_ENDPOINT: NLA_MIN_LEN(struct sockaddr), struct sockaddr_in or struct sockaddr_in6
|
||||
* WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16
|
||||
* WGPEER_A_LAST_HANDSHAKE_TIME: struct __kernel_timespec
|
||||
* WGPEER_A_LAST_HANDSHAKE_TIME: NLA_EXACT_LEN, struct __kernel_timespec
|
||||
* WGPEER_A_RX_BYTES: NLA_U64
|
||||
* WGPEER_A_TX_BYTES: NLA_U64
|
||||
* WGPEER_A_ALLOWEDIPS: NLA_NESTED
|
||||
* 0: NLA_NESTED
|
||||
* WGALLOWEDIP_A_FAMILY: NLA_U16
|
||||
* WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr
|
||||
* WGALLOWEDIP_A_IPADDR: NLA_MIN_LEN(struct in_addr), struct in_addr or struct in6_addr
|
||||
* WGALLOWEDIP_A_CIDR_MASK: NLA_U8
|
||||
* 0: NLA_NESTED
|
||||
* ...
|
||||
|
@ -77,7 +77,7 @@
|
|||
* WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME:
|
||||
*
|
||||
* WGDEVICE_A_IFINDEX: NLA_U32
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1
|
||||
* WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1
|
||||
* WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current
|
||||
* peers should be removed prior to adding the list below.
|
||||
* WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove
|
||||
|
@ -87,10 +87,12 @@
|
|||
* 0: NLA_NESTED
|
||||
* WGPEER_A_PUBLIC_KEY: len WG_KEY_LEN
|
||||
* WGPEER_A_FLAGS: NLA_U32, 0 and/or WGPEER_F_REMOVE_ME if the
|
||||
* specified peer should be removed rather than
|
||||
* added/updated and/or WGPEER_F_REPLACE_ALLOWEDIPS
|
||||
* if all current allowed IPs of this peer should be
|
||||
* removed prior to adding the list below.
|
||||
* specified peer should not exist at the end of the
|
||||
* operation, rather than added/updated and/or
|
||||
* WGPEER_F_REPLACE_ALLOWEDIPS if all current allowed
|
||||
* IPs of this peer should be removed prior to adding
|
||||
* the list below and/or WGPEER_F_UPDATE_ONLY if the
|
||||
* peer should only be set if it already exists.
|
||||
* WGPEER_A_PRESHARED_KEY: len WG_KEY_LEN, all zeros to remove
|
||||
* WGPEER_A_ENDPOINT: struct sockaddr_in or struct sockaddr_in6
|
||||
* WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL: NLA_U16, 0 to disable
|
||||
|
@ -119,7 +121,7 @@
|
|||
* filling in information not contained in the prior. Note that if
|
||||
* WGDEVICE_F_REPLACE_PEERS is specified in the first message, it probably
|
||||
* should not be specified in fragments that come after, so that the list
|
||||
* of peers is only cleared the first time but appened after. Likewise for
|
||||
* of peers is only cleared the first time but appended after. Likewise for
|
||||
* peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the first message
|
||||
* of a peer, it likely should not be specified in subsequent fragments.
|
||||
*
|
||||
|
@ -142,7 +144,8 @@ enum wg_cmd {
|
|||
#define WG_CMD_MAX (__WG_CMD_MAX - 1)
|
||||
|
||||
enum wgdevice_flag {
|
||||
WGDEVICE_F_REPLACE_PEERS = 1U << 0
|
||||
WGDEVICE_F_REPLACE_PEERS = 1U << 0,
|
||||
__WGDEVICE_F_ALL = WGDEVICE_F_REPLACE_PEERS
|
||||
};
|
||||
enum wgdevice_attribute {
|
||||
WGDEVICE_A_UNSPEC,
|
||||
|
@ -160,7 +163,10 @@ enum wgdevice_attribute {
|
|||
|
||||
enum wgpeer_flag {
|
||||
WGPEER_F_REMOVE_ME = 1U << 0,
|
||||
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1
|
||||
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
|
||||
WGPEER_F_UPDATE_ONLY = 1U << 2,
|
||||
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
|
||||
WGPEER_F_UPDATE_ONLY
|
||||
};
|
||||
enum wgpeer_attribute {
|
||||
WGPEER_A_UNSPEC,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
|
@ -909,7 +910,7 @@ static const char* const ip_tos_table[] = {
|
|||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(ip_tos, int, 0xff);
|
||||
|
||||
bool ifname_valid(const char *p) {
|
||||
bool ifname_valid_full(const char *p, bool alternative) {
|
||||
bool numeric = true;
|
||||
|
||||
/* Checks whether a network interface name is valid. This is inspired by dev_valid_name() in the kernel sources
|
||||
|
@ -919,8 +920,13 @@ bool ifname_valid(const char *p) {
|
|||
if (isempty(p))
|
||||
return false;
|
||||
|
||||
if (strlen(p) >= IFNAMSIZ)
|
||||
return false;
|
||||
if (alternative) {
|
||||
if (strlen(p) >= ALTIFNAMSIZ)
|
||||
return false;
|
||||
} else {
|
||||
if (strlen(p) >= IFNAMSIZ)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dot_or_dot_dot(p))
|
||||
return false;
|
||||
|
|
|
@ -130,7 +130,10 @@ int fd_inc_rcvbuf(int fd, size_t n);
|
|||
int ip_tos_to_string_alloc(int i, char **s);
|
||||
int ip_tos_from_string(const char *s);
|
||||
|
||||
bool ifname_valid(const char *p);
|
||||
bool ifname_valid_full(const char *p, bool alternative);
|
||||
static inline bool ifname_valid(const char *p) {
|
||||
return ifname_valid_full(p, false);
|
||||
}
|
||||
bool address_label_valid(const char *p);
|
||||
|
||||
int getpeercred(int fd, struct ucred *ucred);
|
||||
|
|
|
@ -67,7 +67,7 @@ int fopen_temporary(const char *path, FILE **ret_f, char **ret_temp_path) {
|
|||
|
||||
/* This is much like mkostemp() but is subject to umask(). */
|
||||
int mkostemp_safe(char *pattern) {
|
||||
int fd;
|
||||
int fd = -1; /* avoid false maybe-uninitialized warning */
|
||||
|
||||
assert(pattern);
|
||||
|
||||
|
|
|
@ -1163,6 +1163,15 @@ static void read_loader_efi_var(const char *name, char **var) {
|
|||
log_warning_errno(r, "Failed to read EFI variable %s: %m", name);
|
||||
}
|
||||
|
||||
static void print_yes_no_line(bool first, bool good, const char *name) {
|
||||
printf("%s%s%s%s %s\n",
|
||||
first ? " Features: " : " ",
|
||||
good ? ansi_highlight_green() : ansi_highlight_red(),
|
||||
good ? special_glyph(SPECIAL_GLYPH_CHECK_MARK) : special_glyph(SPECIAL_GLYPH_CROSS_MARK),
|
||||
ansi_normal(),
|
||||
name);
|
||||
}
|
||||
|
||||
static int verb_status(int argc, char *argv[], void *userdata) {
|
||||
sd_id128_t esp_uuid = SD_ID128_NULL, xbootldr_uuid = SD_ID128_NULL;
|
||||
int r, k;
|
||||
|
@ -1242,18 +1251,15 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||
printf("Current Boot Loader:\n");
|
||||
printf(" Product: %s%s%s\n", ansi_highlight(), strna(loader), ansi_normal());
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(flags); i++) {
|
||||
for (i = 0; i < ELEMENTSOF(flags); i++)
|
||||
print_yes_no_line(i == 0, FLAGS_SET(loader_features, flags[i].flag), flags[i].name);
|
||||
|
||||
if (i == 0)
|
||||
printf(" Features: ");
|
||||
else
|
||||
printf(" ");
|
||||
sd_id128_t bootloader_esp_uuid;
|
||||
bool have_bootloader_esp_uuid = efi_loader_get_device_part_uuid(&bootloader_esp_uuid) >= 0;
|
||||
|
||||
if (FLAGS_SET(loader_features, flags[i].flag))
|
||||
printf("%s%s%s %s\n", ansi_highlight_green(), special_glyph(SPECIAL_GLYPH_CHECK_MARK), ansi_normal(), flags[i].name);
|
||||
else
|
||||
printf("%s%s%s %s\n", ansi_highlight_red(), special_glyph(SPECIAL_GLYPH_CROSS_MARK), ansi_normal(), flags[i].name);
|
||||
}
|
||||
print_yes_no_line(false, have_bootloader_esp_uuid, "Boot loader sets ESP partition information");
|
||||
if (have_bootloader_esp_uuid && !sd_id128_equal(esp_uuid, bootloader_esp_uuid))
|
||||
printf("WARNING: The boot loader reports different ESP UUID then detected!\n");
|
||||
|
||||
if (stub)
|
||||
printf(" Stub: %s\n", stub);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "device-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "dissect-image.h"
|
||||
#include "dropin.h"
|
||||
#include "efi-loader.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
|
@ -39,6 +40,70 @@ static bool arg_enabled = true;
|
|||
static bool arg_root_enabled = true;
|
||||
static int arg_root_rw = -1;
|
||||
|
||||
static int open_parent_block_device(dev_t devnum, int *ret_fd) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
const char *name, *devtype, *node;
|
||||
sd_device *parent;
|
||||
dev_t pn;
|
||||
int fd, r;
|
||||
|
||||
assert(ret_fd);
|
||||
|
||||
r = sd_device_new_from_devnum(&d, 'b', devnum);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to open device: %m");
|
||||
|
||||
if (sd_device_get_devname(d, &name) < 0) {
|
||||
r = sd_device_get_syspath(d, &name);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Device %u:%u does not have a name, ignoring: %m",
|
||||
major(devnum), minor(devnum));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_device_get_parent(d, &parent);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Not a partitioned device, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Does it have a devtype? */
|
||||
r = sd_device_get_devtype(parent, &devtype);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent doesn't have a device type, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is this a disk or a partition? We only care for disks... */
|
||||
if (!streq(devtype, "disk")) {
|
||||
log_device_debug(parent, "Parent isn't a raw disk, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Does it have a device node? */
|
||||
r = sd_device_get_devname(parent, &node);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent device does not have device node, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_device_debug(d, "Root device %s.", node);
|
||||
|
||||
r = sd_device_get_devnum(parent, &pn);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent device is not a proper block device, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(node, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", node);
|
||||
|
||||
*ret_fd = fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int add_cryptsetup(const char *id, const char *what, bool rw, bool require, char **device) {
|
||||
_cleanup_free_ char *e = NULL, *n = NULL, *d = NULL, *id_escaped = NULL, *what_escaped = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
@ -103,28 +168,25 @@ static int add_cryptsetup(const char *id, const char *what, bool rw, bool requir
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (require) {
|
||||
const char *dmname;
|
||||
const char *dmname;
|
||||
dmname = strjoina("dev-mapper-", e, ".device");
|
||||
|
||||
if (require) {
|
||||
r = generator_add_symlink(arg_dest, "cryptsetup.target", "requires", n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
dmname = strjoina("dev-mapper-", e, ".device");
|
||||
r = generator_add_symlink(arg_dest, dmname, "requires", n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
p = strjoina(arg_dest, "/dev-mapper-", e, ".device.d/50-job-timeout-sec-0.conf");
|
||||
mkdir_parents_label(p, 0755);
|
||||
r = write_string_file(p,
|
||||
"# Automatically generated by systemd-gpt-auto-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"JobTimeoutSec=0\n",
|
||||
WRITE_STRING_FILE_CREATE); /* the binary handles timeouts anyway */
|
||||
r = write_drop_in_format(arg_dest, dmname, 50, "job-timeout",
|
||||
"# Automatically generated by systemd-gpt-auto-generator\n\n"
|
||||
"[Unit]\n"
|
||||
"JobTimeoutSec=0"); /* the binary handles timeouts anyway */
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to write device drop-in: %m");
|
||||
log_warning_errno(r, "Failed to write device timeout drop-in, ignoring: %m");
|
||||
|
||||
if (device) {
|
||||
char *ret;
|
||||
|
@ -162,7 +224,7 @@ static int add_mount(
|
|||
assert(where);
|
||||
assert(description);
|
||||
|
||||
log_debug("Adding %s: %s %s", where, what, strna(fstype));
|
||||
log_debug("Adding %s: %s fstype=%s", where, what, fstype ?: "(any)");
|
||||
|
||||
if (streq_ptr(fstype, "crypto_LUKS")) {
|
||||
|
||||
|
@ -530,67 +592,62 @@ static int add_root_rw(DissectedPartition *p) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int open_parent_devno(dev_t devnum, int *ret) {
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
const char *name, *devtype, *node;
|
||||
sd_device *parent;
|
||||
dev_t pn;
|
||||
int fd, r;
|
||||
#if ENABLE_EFI
|
||||
static int add_root_cryptsetup(void) {
|
||||
|
||||
assert(ret);
|
||||
/* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which
|
||||
* sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */
|
||||
|
||||
r = sd_device_new_from_devnum(&d, 'b', devnum);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to open device: %m");
|
||||
return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sd_device_get_devname(d, &name) < 0) {
|
||||
r = sd_device_get_syspath(d, &name);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Device %u:%u does not have a name, ignoring: %m", major(devnum), minor(devnum));
|
||||
static int add_root_mount(void) {
|
||||
#if ENABLE_EFI
|
||||
int r;
|
||||
|
||||
if (!is_efi_boot()) {
|
||||
log_debug("Not a EFI boot, not creating root mount.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_loader_get_device_part_uuid(NULL);
|
||||
if (r == -ENOENT) {
|
||||
log_notice("EFI loader partition unknown, exiting.\n"
|
||||
"(The boot loader did not set EFI variable LoaderDevicePartUUID.)");
|
||||
return 0;
|
||||
} else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read ESP partition UUID: %m");
|
||||
|
||||
/* OK, we have an ESP partition, this is fantastic, so let's
|
||||
* wait for a root device to show up. A udev rule will create
|
||||
* the link for us under the right name. */
|
||||
|
||||
if (in_initrd()) {
|
||||
r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root");
|
||||
if (r < 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = add_root_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_device_get_parent(d, &parent);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(d, r, "Not a partitioned device, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
/* Note that we do not need to enable systemd-remount-fs.service here. If
|
||||
* /etc/fstab exists, systemd-fstab-generator will pull it in for us. */
|
||||
|
||||
/* Does it have a devtype? */
|
||||
r = sd_device_get_devtype(parent, &devtype);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent doesn't have a device type, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Is this a disk or a partition? We only care for disks... */
|
||||
if (!streq(devtype, "disk")) {
|
||||
log_device_debug(parent, "Parent isn't a raw disk, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Does it have a device node? */
|
||||
r = sd_device_get_devname(parent, &node);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent device does not have device node, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_device_debug(d, "Root device %s.", node);
|
||||
|
||||
r = sd_device_get_devnum(parent, &pn);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(parent, r, "Parent device is not a proper block device, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(node, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return log_error_errno(errno, "Failed to open %s: %m", node);
|
||||
|
||||
*ret = fd;
|
||||
return 1;
|
||||
return add_mount(
|
||||
"root",
|
||||
"/dev/gpt-auto-root",
|
||||
in_initrd() ? "/sysroot" : "/",
|
||||
NULL,
|
||||
arg_root_rw > 0,
|
||||
NULL,
|
||||
"Root Partition",
|
||||
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int enumerate_partitions(dev_t devnum) {
|
||||
|
@ -598,7 +655,7 @@ static int enumerate_partitions(dev_t devnum) {
|
|||
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
|
||||
int r, k;
|
||||
|
||||
r = open_parent_devno(devnum, &fd);
|
||||
r = open_parent_block_device(devnum, &fd);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
|
@ -649,105 +706,6 @@ static int enumerate_partitions(dev_t devnum) {
|
|||
return r;
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
int r;
|
||||
|
||||
assert(key);
|
||||
|
||||
if (proc_cmdline_key_streq(key, "systemd.gpt_auto") ||
|
||||
proc_cmdline_key_streq(key, "rd.systemd.gpt_auto")) {
|
||||
|
||||
r = value ? parse_boolean(value) : 1;
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse gpt-auto switch \"%s\", ignoring: %m", value);
|
||||
else
|
||||
arg_enabled = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "root")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
/* Disable root disk logic if there's a root= value
|
||||
* specified (unless it happens to be "gpt-auto") */
|
||||
|
||||
arg_root_enabled = streq(value, "gpt-auto");
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "roothash")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
/* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */
|
||||
|
||||
arg_root_enabled = false;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "rw") && !value)
|
||||
arg_root_rw = true;
|
||||
else if (proc_cmdline_key_streq(key, "ro") && !value)
|
||||
arg_root_rw = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ENABLE_EFI
|
||||
static int add_root_cryptsetup(void) {
|
||||
|
||||
/* If a device /dev/gpt-auto-root-luks appears, then make it pull in systemd-cryptsetup-root.service, which
|
||||
* sets it up, and causes /dev/gpt-auto-root to appear which is all we are looking for. */
|
||||
|
||||
return add_cryptsetup("root", "/dev/gpt-auto-root-luks", true, false, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_root_mount(void) {
|
||||
|
||||
#if ENABLE_EFI
|
||||
int r;
|
||||
|
||||
if (!is_efi_boot()) {
|
||||
log_debug("Not a EFI boot, not creating root mount.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = efi_loader_get_device_part_uuid(NULL);
|
||||
if (r == -ENOENT) {
|
||||
log_debug("EFI loader partition unknown, exiting.");
|
||||
return 0;
|
||||
} else if (r < 0)
|
||||
return log_error_errno(r, "Failed to read ESP partition UUID: %m");
|
||||
|
||||
/* OK, we have an ESP partition, this is fantastic, so let's
|
||||
* wait for a root device to show up. A udev rule will create
|
||||
* the link for us under the right name. */
|
||||
|
||||
if (in_initrd()) {
|
||||
r = generator_write_initrd_root_device_deps(arg_dest, "/dev/gpt-auto-root");
|
||||
if (r < 0)
|
||||
return 0;
|
||||
|
||||
r = add_root_cryptsetup();
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Note that we do not need to enable systemd-remount-fs.service here. If
|
||||
* /etc/fstab exists, systemd-fstab-generator will pull it in for us. */
|
||||
|
||||
return add_mount(
|
||||
"root",
|
||||
"/dev/gpt-auto-root",
|
||||
in_initrd() ? "/sysroot" : "/",
|
||||
NULL,
|
||||
arg_root_rw > 0,
|
||||
NULL,
|
||||
"Root Partition",
|
||||
in_initrd() ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_LOCAL_FS_TARGET);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int add_mounts(void) {
|
||||
dev_t devno;
|
||||
int r;
|
||||
|
@ -785,6 +743,50 @@ static int add_mounts(void) {
|
|||
return enumerate_partitions(devno);
|
||||
}
|
||||
|
||||
static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
|
||||
int r;
|
||||
|
||||
assert(key);
|
||||
|
||||
if (proc_cmdline_key_streq(key, "systemd.gpt_auto") ||
|
||||
proc_cmdline_key_streq(key, "rd.systemd.gpt_auto")) {
|
||||
|
||||
r = value ? parse_boolean(value) : 1;
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to parse gpt-auto switch \"%s\", ignoring: %m", value);
|
||||
else
|
||||
arg_enabled = r;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "root")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
/* Disable root disk logic if there's a root= value
|
||||
* specified (unless it happens to be "gpt-auto") */
|
||||
|
||||
if (!streq(value, "gpt-auto")) {
|
||||
arg_root_enabled = false;
|
||||
log_debug("Disabling root partition auto-detection, root= is defined.");
|
||||
}
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "roothash")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
/* Disable root disk logic if there's roothash= defined (i.e. verity enabled) */
|
||||
|
||||
arg_root_enabled = false;
|
||||
|
||||
} else if (proc_cmdline_key_streq(key, "rw") && !value)
|
||||
arg_root_rw = true;
|
||||
else if (proc_cmdline_key_streq(key, "ro") && !value)
|
||||
arg_root_rw = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run(const char *dest, const char *dest_early, const char *dest_late) {
|
||||
int r, k;
|
||||
|
||||
|
|
|
@ -103,6 +103,18 @@ static bool net_condition_test_strv(char * const *patterns, const char *string)
|
|||
return has_positive_rule ? match : true;
|
||||
}
|
||||
|
||||
static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) {
|
||||
if (net_condition_test_strv(patterns, ifname))
|
||||
return true;
|
||||
|
||||
char * const *p;
|
||||
STRV_FOREACH(p, alternative_names)
|
||||
if (net_condition_test_strv(patterns, *p))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int net_condition_test_property(char * const *match_property, sd_device *device) {
|
||||
char * const *p;
|
||||
|
||||
|
@ -166,6 +178,7 @@ bool net_match_config(Set *match_mac,
|
|||
sd_device *device,
|
||||
const struct ether_addr *dev_mac,
|
||||
const char *dev_name,
|
||||
char * const *alternative_names,
|
||||
enum nl80211_iftype wifi_iftype,
|
||||
const char *ssid,
|
||||
const struct ether_addr *bssid) {
|
||||
|
@ -196,7 +209,7 @@ bool net_match_config(Set *match_mac,
|
|||
if (!net_condition_test_strv(match_types, dev_type))
|
||||
return false;
|
||||
|
||||
if (!net_condition_test_strv(match_names, dev_name))
|
||||
if (!net_condition_test_ifname(match_names, dev_name, alternative_names))
|
||||
return false;
|
||||
|
||||
if (!net_condition_test_property(match_property, device))
|
||||
|
@ -349,7 +362,7 @@ int config_parse_match_ifnames(
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!ifname_valid(word)) {
|
||||
if (!ifname_valid_full(word, ltype)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Interface name is not valid or too long, ignoring assignment: %s", word);
|
||||
continue;
|
||||
|
|
|
@ -27,6 +27,7 @@ bool net_match_config(Set *match_mac,
|
|||
sd_device *device,
|
||||
const struct ether_addr *dev_mac,
|
||||
const char *dev_name,
|
||||
char * const *alternative_names,
|
||||
enum nl80211_iftype wifi_iftype,
|
||||
const char *ssid,
|
||||
const struct ether_addr *bssid);
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
|
||||
#include "alloc-util.h"
|
||||
#include "format-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-types.h"
|
||||
#include "netlink-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
|
||||
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
|
||||
|
@ -86,7 +87,8 @@ int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
|
|||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
|
||||
assert_return(IN_SET(m->hdr->nlmsg_type, RTM_GETLINK, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH,
|
||||
assert_return(IN_SET(m->hdr->nlmsg_type,
|
||||
RTM_GETLINK, RTM_GETLINKPROP, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH,
|
||||
RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP), -EINVAL);
|
||||
|
||||
SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
|
||||
|
@ -248,6 +250,35 @@ int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data) {
|
||||
size_t length, size;
|
||||
char * const *p;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(data, -EINVAL);
|
||||
|
||||
r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(p, data) {
|
||||
if (size) {
|
||||
length = strnlen(*p, size+1);
|
||||
if (length > size)
|
||||
return -EINVAL;
|
||||
} else
|
||||
length = strlen(*p);
|
||||
|
||||
r = add_rtattr(m, type, *p, length + 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) {
|
||||
size_t size;
|
||||
int r;
|
||||
|
@ -827,6 +858,63 @@ int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
const NLTypeSystem *type_system;
|
||||
const NLType *nl_type;
|
||||
struct rtattr *rta;
|
||||
void *container;
|
||||
unsigned short rt_len;
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
|
||||
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
container_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
|
||||
return -EINVAL;
|
||||
|
||||
r = type_system_get_type_system(m->containers[m->n_containers].type_system,
|
||||
&type_system,
|
||||
container_type);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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;
|
||||
|
||||
r = netlink_message_read_internal(m, container_type, &container, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
rt_len = (unsigned short) r;
|
||||
rta = container;
|
||||
|
||||
for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
|
||||
unsigned short type;
|
||||
|
||||
type = RTA_TYPE(rta);
|
||||
if (type != type_id)
|
||||
continue;
|
||||
|
||||
r = strv_extend(&s, RTA_DATA(rta));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netlink_container_parse(sd_netlink_message *m,
|
||||
struct netlink_container *container,
|
||||
struct rtattr *rta,
|
||||
|
|
|
@ -527,6 +527,15 @@ static const NLTypeSystem rtnl_af_spec_type_system = {
|
|||
.types = rtnl_af_spec_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_prop_list_types[] = {
|
||||
[IFLA_ALT_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = ALTIFNAMSIZ - 1 },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_prop_list_type_system = {
|
||||
.count = ELEMENTSOF(rtnl_prop_list_types),
|
||||
.types = rtnl_prop_list_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_types[] = {
|
||||
[IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
|
@ -581,8 +590,9 @@ static const NLType rtnl_link_types[] = {
|
|||
/*
|
||||
[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_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 },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_link_type_system = {
|
||||
|
@ -824,6 +834,9 @@ static const NLType rtnl_types[] = {
|
|||
[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) },
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "netlink-internal.h"
|
||||
#include "netlink-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
|
@ -83,6 +84,45 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
assert(ifindex > 0);
|
||||
|
||||
if (strv_isempty(alternative_names))
|
||||
return 0;
|
||||
|
||||
if (!*rtnl) {
|
||||
r = sd_netlink_open(rtnl);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_rtnl_message_new_link(*rtnl, &message, RTM_NEWLINKPROP, ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_open_container(message, IFLA_PROP_LIST);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_append_strv(message, IFLA_ALT_IFNAME, alternative_names);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_close_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_call(*rtnl, message, 0, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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;
|
||||
|
|
|
@ -26,7 +26,9 @@ static inline bool rtnl_message_type_is_nexthop(uint16_t type) {
|
|||
}
|
||||
|
||||
static inline bool rtnl_message_type_is_link(uint16_t type) {
|
||||
return IN_SET(type, RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK);
|
||||
return IN_SET(type,
|
||||
RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK,
|
||||
RTM_NEWLINKPROP, RTM_DELLINKPROP, RTM_GETLINKPROP);
|
||||
}
|
||||
|
||||
static inline bool rtnl_message_type_is_addr(uint16_t type) {
|
||||
|
@ -47,6 +49,7 @@ static inline bool rtnl_message_type_is_qdisc(uint16_t type) {
|
|||
|
||||
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
|
||||
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, uint32_t mtu);
|
||||
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
|
||||
|
||||
int rtnl_log_parse_error(int r);
|
||||
int rtnl_log_create_error(int r);
|
||||
|
|
|
@ -512,6 +512,8 @@ int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
|
|||
|
||||
if (nlmsg_type == RTM_NEWLINK)
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
|
||||
else if (nlmsg_type == RTM_NEWLINK)
|
||||
(*ret)->hdr->nlmsg_flags |= NLM_F_EXCL | NLM_F_CREATE | NLM_F_APPEND;
|
||||
|
||||
ifi = NLMSG_DATA((*ret)->hdr);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
|
||||
static void test_message_link_bridge(sd_netlink *rtnl) {
|
||||
|
@ -547,7 +548,36 @@ static void test_array(void) {
|
|||
assert_se(streq(name, expected));
|
||||
}
|
||||
assert_se(sd_netlink_message_exit_container(m) >= 0);
|
||||
}
|
||||
|
||||
static void test_strv(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
|
||||
_cleanup_strv_free_ char **names_in = NULL, **names_out;
|
||||
const char *p;
|
||||
|
||||
assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINKPROP, 1) >= 0);
|
||||
|
||||
for (unsigned i = 0; i < 10; i++) {
|
||||
char name[STRLEN("hoge") + DECIMAL_STR_MAX(uint32_t)];
|
||||
|
||||
xsprintf(name, "hoge%" PRIu32, i + 1000);
|
||||
assert_se(strv_extend(&names_in, name) >= 0);
|
||||
}
|
||||
|
||||
assert_se(sd_netlink_message_open_container(m, IFLA_PROP_LIST) >= 0);
|
||||
assert_se(sd_netlink_message_append_strv(m, IFLA_ALT_IFNAME, names_in) >= 0);
|
||||
assert_se(sd_netlink_message_close_container(m) >= 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));
|
||||
|
||||
assert_se(sd_netlink_message_enter_container(m, IFLA_PROP_LIST) >= 0);
|
||||
assert_se(sd_netlink_message_read_string(m, IFLA_ALT_IFNAME, &p) >= 0);
|
||||
assert_se(streq(p, "hoge1009"));
|
||||
assert_se(sd_netlink_message_exit_container(m) >= 0);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
|
@ -568,6 +598,7 @@ int main(void) {
|
|||
test_message(rtnl);
|
||||
test_container(rtnl);
|
||||
test_array();
|
||||
test_strv(rtnl);
|
||||
|
||||
if_loopback = (int) if_nametoindex("lo");
|
||||
assert_se(if_loopback > 0);
|
||||
|
|
|
@ -139,6 +139,7 @@ typedef struct LinkInfo {
|
|||
uint32_t max_mtu;
|
||||
uint32_t tx_queues;
|
||||
uint32_t rx_queues;
|
||||
char **alternative_names;
|
||||
|
||||
union {
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
@ -191,6 +192,7 @@ static const LinkInfo* link_info_array_free(LinkInfo *array) {
|
|||
for (unsigned i = 0; array && array[i].needs_freeing; i++) {
|
||||
sd_device_unref(array[i].sd_device);
|
||||
free(array[i].ssid);
|
||||
strv_free(array[i].alternative_names);
|
||||
}
|
||||
|
||||
return mfree(array);
|
||||
|
@ -304,6 +306,7 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns) {
|
|||
(void) sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu);
|
||||
(void) sd_netlink_message_read_u32(m, IFLA_MIN_MTU, &info->min_mtu);
|
||||
(void) sd_netlink_message_read_u32(m, IFLA_MAX_MTU, &info->max_mtu);
|
||||
(void) sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &info->alternative_names);
|
||||
|
||||
info->has_rx_queues =
|
||||
sd_netlink_message_read_u32(m, IFLA_NUM_RX_QUEUES, &info->rx_queues) >= 0 &&
|
||||
|
@ -1063,6 +1066,7 @@ static int link_status_one(
|
|||
_cleanup_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL;
|
||||
_cleanup_(table_unrefp) Table *table = NULL;
|
||||
TableCell *cell;
|
||||
char **p;
|
||||
int r;
|
||||
|
||||
assert(rtnl);
|
||||
|
@ -1144,6 +1148,18 @@ static int link_status_one(
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(p, info->alternative_names)
|
||||
if (p == info->alternative_names)
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, "Alternative Names:",
|
||||
TABLE_STRING, *p);
|
||||
else
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
TABLE_EMPTY,
|
||||
TABLE_STRING, *p);
|
||||
|
||||
if (path) {
|
||||
r = table_add_many(table,
|
||||
TABLE_EMPTY,
|
||||
|
|
|
@ -180,7 +180,9 @@ int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32
|
|||
/* master needs flag self */
|
||||
if (!link->network->bridge) {
|
||||
flags = BRIDGE_FLAGS_SELF;
|
||||
sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t));
|
||||
r = sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t));
|
||||
if (r < 0)
|
||||
return log_link_error_errno(link, r, "Could not open IFLA_BRIDGE_FLAGS: %m");
|
||||
}
|
||||
|
||||
/* add vlan info */
|
||||
|
|
|
@ -542,10 +542,10 @@ static int link_update_flags(Link *link, sd_netlink_message *m, bool force_updat
|
|||
|
||||
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
|
||||
_cleanup_(link_unrefp) Link *link = NULL;
|
||||
uint16_t type;
|
||||
const char *ifname, *kind = NULL;
|
||||
int r, ifindex;
|
||||
unsigned short iftype;
|
||||
int r, ifindex;
|
||||
uint16_t type;
|
||||
|
||||
assert(manager);
|
||||
assert(message);
|
||||
|
@ -617,6 +617,10 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
|
|||
if (r < 0)
|
||||
log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
|
||||
|
||||
r = sd_netlink_message_read_strv(message, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &link->alternative_names);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
|
||||
if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -713,6 +717,7 @@ static Link *link_free(Link *link) {
|
|||
free(link->lldp_file);
|
||||
|
||||
free(link->ifname);
|
||||
strv_free(link->alternative_names);
|
||||
free(link->kind);
|
||||
free(link->ssid);
|
||||
|
||||
|
@ -2934,14 +2939,28 @@ static int link_configure_duid(Link *link) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int link_reconfigure(Link *link, bool force) {
|
||||
static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool force) {
|
||||
Network *network;
|
||||
int r;
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_LINGER))
|
||||
return 0;
|
||||
|
||||
r = network_get(link->manager, link->sd_device, link->ifname,
|
||||
if (m) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
|
||||
strv_free_and_replace(link->alternative_names, s);
|
||||
}
|
||||
|
||||
r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
|
||||
&link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
|
||||
if (r == -ENOENT) {
|
||||
link_enter_unmanaged(link);
|
||||
|
@ -2959,10 +2978,8 @@ int link_reconfigure(Link *link, bool force) {
|
|||
|
||||
/* Dropping old .network file */
|
||||
r = link_stop_clients(link, false);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link_dhcp4_server_enabled(link))
|
||||
(void) sd_dhcp_server_stop(link->dhcp_server);
|
||||
|
@ -3006,6 +3023,46 @@ int link_reconfigure(Link *link, bool force) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int link_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_reconfigure_internal(link, m, false);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int link_force_reconfigure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
int r;
|
||||
|
||||
r = link_reconfigure_internal(link, m, true);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int link_reconfigure(Link *link, bool force) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK,
|
||||
link->ifindex);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = netlink_call_async(link->manager->rtnl, NULL, req,
|
||||
force ? link_force_reconfigure_handler : link_reconfigure_handler,
|
||||
link_netlink_destroy_callback, link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
link_ref(link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_initialized_and_synced(Link *link) {
|
||||
Network *network;
|
||||
int r;
|
||||
|
@ -3035,7 +3092,7 @@ static int link_initialized_and_synced(Link *link) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_get(link->manager, link->sd_device, link->ifname,
|
||||
r = network_get(link->manager, link->sd_device, link->ifname, link->alternative_names,
|
||||
&link->mac, link->wlan_iftype, link->ssid, &link->bssid, &network);
|
||||
if (r == -ENOENT) {
|
||||
link_enter_unmanaged(link);
|
||||
|
@ -3080,8 +3137,23 @@ static int link_initialized_and_synced(Link *link) {
|
|||
}
|
||||
|
||||
static int link_initialized_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
|
||||
if (r < 0 && r != -ENODATA) {
|
||||
link_enter_failed(link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strv_free_and_replace(link->alternative_names, s);
|
||||
|
||||
r = link_initialized_and_synced(link);
|
||||
if (r < 0)
|
||||
link_enter_failed(link);
|
||||
|
@ -3414,9 +3486,11 @@ static int link_carrier_gained(Link *link) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
r = link_reconfigure(link, false);
|
||||
if (r < 0)
|
||||
r = link_reconfigure_internal(link, NULL, false);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED)) {
|
||||
|
@ -3520,6 +3594,7 @@ static int link_admin_state_up(Link *link) {
|
|||
}
|
||||
|
||||
int link_update(Link *link, sd_netlink_message *m) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
struct ether_addr mac;
|
||||
const char *ifname;
|
||||
uint32_t mtu;
|
||||
|
@ -3551,6 +3626,10 @@ int link_update(Link *link, sd_netlink_message *m) {
|
|||
return r;
|
||||
}
|
||||
|
||||
r = sd_netlink_message_read_strv(m, IFLA_PROP_LIST, IFLA_ALT_IFNAME, &s);
|
||||
if (r >= 0)
|
||||
strv_free_and_replace(link->alternative_names, s);
|
||||
|
||||
r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu);
|
||||
if (r >= 0 && mtu > 0) {
|
||||
link->mtu = mtu;
|
||||
|
|
|
@ -48,6 +48,7 @@ typedef struct Link {
|
|||
int ifindex;
|
||||
int master_ifindex;
|
||||
char *ifname;
|
||||
char **alternative_names;
|
||||
char *kind;
|
||||
unsigned short iftype;
|
||||
char *state_file;
|
||||
|
|
|
@ -34,7 +34,7 @@ Match.Type, config_parse_match_strv,
|
|||
Match.WLANInterfaceType, config_parse_match_strv, 0, offsetof(Network, match_wlan_iftype)
|
||||
Match.SSID, config_parse_match_strv, 0, offsetof(Network, match_ssid)
|
||||
Match.BSSID, config_parse_hwaddrs, 0, offsetof(Network, match_bssid)
|
||||
Match.Name, config_parse_match_ifnames, 0, offsetof(Network, match_name)
|
||||
Match.Name, config_parse_match_ifnames, 1, offsetof(Network, match_name)
|
||||
Match.Property, config_parse_match_property, 0, offsetof(Network, match_property)
|
||||
Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, conditions)
|
||||
Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, conditions)
|
||||
|
|
|
@ -718,7 +718,7 @@ int network_get_by_name(Manager *manager, const char *name, Network **ret) {
|
|||
}
|
||||
|
||||
int network_get(Manager *manager, sd_device *device,
|
||||
const char *ifname, const struct ether_addr *address,
|
||||
const char *ifname, char * const *alternative_names, const struct ether_addr *address,
|
||||
enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid,
|
||||
Network **ret) {
|
||||
Network *network;
|
||||
|
@ -731,7 +731,7 @@ int network_get(Manager *manager, sd_device *device,
|
|||
if (net_match_config(network->match_mac, network->match_path, network->match_driver,
|
||||
network->match_type, network->match_name, network->match_property,
|
||||
network->match_wlan_iftype, network->match_ssid, network->match_bssid,
|
||||
device, address, ifname, wlan_iftype, ssid, bssid)) {
|
||||
device, address, ifname, alternative_names, wlan_iftype, ssid, bssid)) {
|
||||
if (network->match_name && device) {
|
||||
const char *attr;
|
||||
uint8_t name_assign_type = NET_NAME_UNKNOWN;
|
||||
|
|
|
@ -297,8 +297,9 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
|
|||
int network_verify(Network *network);
|
||||
|
||||
int network_get_by_name(Manager *manager, const char *name, Network **ret);
|
||||
int network_get(Manager *manager, sd_device *device, const char *ifname, const struct ether_addr *mac,
|
||||
enum nl80211_iftype wlan_iftype, const char *ssid, const struct ether_addr *bssid, Network **ret);
|
||||
int network_get(Manager *manager, sd_device *device, const char *ifname, char * const *alternative_names,
|
||||
const struct ether_addr *mac, enum nl80211_iftype wlan_iftype, const char *ssid,
|
||||
const struct ether_addr *bssid, Network **ret);
|
||||
int network_apply(Network *network, Link *link);
|
||||
void network_apply_anonymize_if_set(Network *network);
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ static void test_network_get(Manager *manager, sd_device *loopback) {
|
|||
|
||||
/* let's assume that the test machine does not have a .network file
|
||||
that applies to the loopback device... */
|
||||
assert_se(network_get(manager, loopback, "lo", &mac, 0, NULL, NULL, &network) == -ENOENT);
|
||||
assert_se(network_get(manager, loopback, "lo", NULL, &mac, 0, NULL, NULL, &network) == -ENOENT);
|
||||
assert_se(!network);
|
||||
}
|
||||
|
||||
|
|
|
@ -985,6 +985,66 @@ int config_parse_ifname(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ifnames(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
char ***s = data;
|
||||
const char *p;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*s = strv_free(*s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = rvalue;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *word = NULL;
|
||||
|
||||
r = extract_first_word(&p, &word, NULL, 0);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||
"Failed to extract interface name, ignoring assignment: %s",
|
||||
rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (!ifname_valid_full(word, ltype)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||
"Interface name is not valid or too long, ignoring assignment: %s",
|
||||
word);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_consume(&names, TAKE_PTR(word));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
r = strv_extend_strv(s, names, true);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_ip_port(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
|
|
|
@ -137,6 +137,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_signal);
|
|||
CONFIG_PARSER_PROTOTYPE(config_parse_personality);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_permille);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ifnames);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
|
||||
|
|
|
@ -562,17 +562,20 @@ int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
|
|||
|
||||
r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeInitUSec", &x);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_debug_errno(r, "Failed to read LoaderTimeInitUSec: %m");
|
||||
|
||||
r = read_usec(EFI_VENDOR_LOADER, "LoaderTimeExecUSec", &y);
|
||||
if (r < 0)
|
||||
return r;
|
||||
return log_debug_errno(r, "Failed to read LoaderTimeExecUSec: %m");
|
||||
|
||||
if (y == 0 || y < x)
|
||||
return -EIO;
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"Bad LoaderTimeInitUSec=%"PRIu64", LoaderTimeExecUSec=%" PRIu64"; refusing.",
|
||||
x, y);
|
||||
|
||||
if (y > USEC_PER_HOUR)
|
||||
return -EIO;
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EIO),
|
||||
"LoaderTimeExecUSec=%"PRIu64" too large, refusing.", x);
|
||||
|
||||
*firmware = x;
|
||||
*loader = y;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <linux/loop.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
|
@ -19,6 +20,14 @@
|
|||
#include "parse-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static void cleanup_clear_loop_close(int *fd) {
|
||||
if (*fd >= 0) {
|
||||
(void) ioctl(*fd, LOOP_CLR_FD);
|
||||
(void) safe_close(*fd);
|
||||
}
|
||||
}
|
||||
|
||||
int loop_device_make_full(
|
||||
int fd,
|
||||
|
@ -28,9 +37,7 @@ int loop_device_make_full(
|
|||
uint32_t loop_flags,
|
||||
LoopDevice **ret) {
|
||||
|
||||
_cleanup_close_ int control = -1, loop = -1;
|
||||
_cleanup_free_ char *loopdev = NULL;
|
||||
unsigned n_attempts = 0;
|
||||
struct loop_info64 info;
|
||||
LoopDevice *d = NULL;
|
||||
struct stat st;
|
||||
|
@ -44,7 +51,7 @@ int loop_device_make_full(
|
|||
return -errno;
|
||||
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
if (ioctl(loop, LOOP_GET_STATUS64, &info) >= 0) {
|
||||
if (ioctl(fd, LOOP_GET_STATUS64, &info) >= 0) {
|
||||
/* Oh! This is a loopback device? That's interesting! */
|
||||
|
||||
#if HAVE_VALGRIND_MEMCHECK_H
|
||||
|
@ -58,7 +65,7 @@ int loop_device_make_full(
|
|||
}
|
||||
|
||||
if (offset == 0 && IN_SET(size, 0, UINT64_MAX)) {
|
||||
int copy;
|
||||
_cleanup_close_ int copy = -1;
|
||||
|
||||
/* If this is already a block device, store a copy of the fd as it is */
|
||||
|
||||
|
@ -69,9 +76,8 @@ int loop_device_make_full(
|
|||
d = new(LoopDevice, 1);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
*d = (LoopDevice) {
|
||||
.fd = copy,
|
||||
.fd = TAKE_FD(copy),
|
||||
.nr = nr,
|
||||
.node = TAKE_PTR(loopdev),
|
||||
.relinquished = true, /* It's not allocated by us, don't destroy it when this object is freed */
|
||||
|
@ -86,13 +92,18 @@ int loop_device_make_full(
|
|||
return r;
|
||||
}
|
||||
|
||||
_cleanup_close_ int control = -1;
|
||||
_cleanup_(cleanup_clear_loop_close) int loop_with_fd = -1;
|
||||
|
||||
control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
|
||||
if (control < 0)
|
||||
return -errno;
|
||||
|
||||
/* Loop around LOOP_CTL_GET_FREE, since at the moment we attempt to open the returned device it might
|
||||
* be gone already, taken by somebody else racing against us. */
|
||||
for (;;) {
|
||||
for (unsigned n_attempts = 0;;) {
|
||||
_cleanup_close_ int loop = -1;
|
||||
|
||||
nr = ioctl(control, LOOP_CTL_GET_FREE);
|
||||
if (nr < 0)
|
||||
return -errno;
|
||||
|
@ -101,19 +112,24 @@ int loop_device_make_full(
|
|||
return -ENOMEM;
|
||||
|
||||
loop = open(loopdev, O_CLOEXEC|O_NONBLOCK|O_NOCTTY|open_flags);
|
||||
if (loop < 0)
|
||||
return -errno;
|
||||
if (ioctl(loop, LOOP_SET_FD, fd) < 0) {
|
||||
if (loop < 0) {
|
||||
/* Somebody might've gotten the same number from the kernel, used the device,
|
||||
* and called LOOP_CTL_REMOVE on it. Let's retry with a new number. */
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
} else {
|
||||
if (ioctl(loop, LOOP_SET_FD, fd) >= 0) {
|
||||
loop_with_fd = TAKE_FD(loop);
|
||||
break;
|
||||
}
|
||||
if (errno != EBUSY)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (++n_attempts >= 64) /* Give up eventually */
|
||||
return -EBUSY;
|
||||
} else
|
||||
break;
|
||||
if (++n_attempts >= 64) /* Give up eventually */
|
||||
return -EBUSY;
|
||||
|
||||
loopdev = mfree(loopdev);
|
||||
loop = safe_close(loop);
|
||||
}
|
||||
|
||||
info = (struct loop_info64) {
|
||||
|
@ -123,33 +139,20 @@ int loop_device_make_full(
|
|||
.lo_sizelimit = size == UINT64_MAX ? 0 : size,
|
||||
};
|
||||
|
||||
if (ioctl(loop, LOOP_SET_STATUS64, &info) < 0) {
|
||||
r = -errno;
|
||||
goto fail;
|
||||
}
|
||||
if (ioctl(loop_with_fd, LOOP_SET_STATUS64, &info) < 0)
|
||||
return -errno;
|
||||
|
||||
d = new(LoopDevice, 1);
|
||||
if (!d) {
|
||||
r = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
*d = (LoopDevice) {
|
||||
.fd = TAKE_FD(loop),
|
||||
.fd = TAKE_FD(loop_with_fd),
|
||||
.node = TAKE_PTR(loopdev),
|
||||
.nr = nr,
|
||||
};
|
||||
|
||||
*ret = d;
|
||||
return d->fd;
|
||||
|
||||
fail:
|
||||
if (fd >= 0)
|
||||
(void) ioctl(fd, LOOP_CLR_FD);
|
||||
if (d && d->fd >= 0)
|
||||
(void) ioctl(d->fd, LOOP_CLR_FD);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, LoopDevice **ret) {
|
||||
|
@ -163,7 +166,7 @@ int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_fla
|
|||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
return loop_device_make(fd, open_flags, loop_flags, ret);
|
||||
return loop_device_make_full(fd, open_flags, 0, 0, loop_flags, ret);
|
||||
}
|
||||
|
||||
LoopDevice* loop_device_unref(LoopDevice *d) {
|
||||
|
@ -171,7 +174,6 @@ LoopDevice* loop_device_unref(LoopDevice *d) {
|
|||
return NULL;
|
||||
|
||||
if (d->fd >= 0) {
|
||||
|
||||
if (d->nr >= 0 && !d->relinquished) {
|
||||
if (ioctl(d->fd, LOOP_CLR_FD) < 0)
|
||||
log_debug_errno(errno, "Failed to clear loop device: %m");
|
||||
|
@ -186,11 +188,19 @@ LoopDevice* loop_device_unref(LoopDevice *d) {
|
|||
|
||||
control = open("/dev/loop-control", O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
|
||||
if (control < 0)
|
||||
log_debug_errno(errno, "Failed to open loop control device: %m");
|
||||
else {
|
||||
if (ioctl(control, LOOP_CTL_REMOVE, d->nr) < 0)
|
||||
log_debug_errno(errno, "Failed to remove loop device: %m");
|
||||
}
|
||||
log_warning_errno(errno,
|
||||
"Failed to open loop control device, cannot remove loop device %s: %m",
|
||||
strna(d->node));
|
||||
else
|
||||
for (unsigned n_attempts = 0;;) {
|
||||
if (ioctl(control, LOOP_CTL_REMOVE, d->nr) >= 0)
|
||||
break;
|
||||
if (errno != EBUSY || ++n_attempts >= 64) {
|
||||
log_warning_errno(errno, "Failed to remove device %s: %m", strna(d->node));
|
||||
break;
|
||||
}
|
||||
usleep(50 * USEC_PER_MSEC);
|
||||
}
|
||||
}
|
||||
|
||||
free(d->node);
|
||||
|
|
|
@ -15,10 +15,6 @@ struct LoopDevice {
|
|||
};
|
||||
|
||||
int loop_device_make_full(int fd, int open_flags, uint64_t offset, uint64_t size, uint32_t loop_flags, LoopDevice **ret);
|
||||
static inline int loop_device_make(int fd, int open_flags, uint32_t loop_flags, LoopDevice **ret) {
|
||||
return loop_device_make_full(fd, open_flags, 0, 0, loop_flags, ret);
|
||||
}
|
||||
|
||||
int loop_device_make_by_path(const char *path, int open_flags, uint32_t loop_flags, LoopDevice **ret);
|
||||
int loop_device_open(const char *loop_path, int open_flags, LoopDevice **ret);
|
||||
|
||||
|
|
|
@ -80,6 +80,7 @@ int sd_netlink_attach_event(sd_netlink *nl, sd_event *e, int64_t priority);
|
|||
int sd_netlink_detach_event(sd_netlink *nl);
|
||||
|
||||
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);
|
||||
int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data);
|
||||
int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data);
|
||||
|
@ -100,6 +101,7 @@ int sd_netlink_message_close_container(sd_netlink_message *m);
|
|||
int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data);
|
||||
int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data);
|
||||
int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data);
|
||||
int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret);
|
||||
int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data);
|
||||
int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data);
|
||||
int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data);
|
||||
|
|
|
@ -45,6 +45,7 @@ static void test_ifname_valid(void) {
|
|||
|
||||
assert(ifname_valid("xxxxxxxxxxxxxxx"));
|
||||
assert(!ifname_valid("xxxxxxxxxxxxxxxx"));
|
||||
assert(ifname_valid_full("xxxxxxxxxxxxxxxx", true));
|
||||
}
|
||||
|
||||
static void test_socket_address_parse_one(const char *in, int ret, int family, const char *expected) {
|
||||
|
|
|
@ -35,6 +35,7 @@ Link.MACAddressPolicy, config_parse_mac_address_policy, 0,
|
|||
Link.MACAddress, config_parse_hwaddr, 0, offsetof(link_config, mac)
|
||||
Link.NamePolicy, config_parse_name_policy, 0, offsetof(link_config, name_policy)
|
||||
Link.Name, config_parse_ifname, 0, offsetof(link_config, name)
|
||||
Link.AlternativeName, config_parse_ifnames, 1, offsetof(link_config, alternative_names)
|
||||
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
|
||||
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
|
||||
Link.BitsPerSecond, config_parse_si_size, 0, offsetof(link_config, speed)
|
||||
|
|
|
@ -58,6 +58,7 @@ static void link_config_free(link_config *link) {
|
|||
free(link->mac);
|
||||
free(link->name_policy);
|
||||
free(link->name);
|
||||
strv_free(link->alternative_names);
|
||||
free(link->alias);
|
||||
|
||||
free(link);
|
||||
|
@ -243,7 +244,7 @@ int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret)
|
|||
LIST_FOREACH(links, link, ctx->links) {
|
||||
if (net_match_config(link->match_mac, link->match_path, link->match_driver,
|
||||
link->match_type, link->match_name, link->match_property, NULL, NULL, NULL,
|
||||
device, NULL, NULL, 0, NULL, NULL)) {
|
||||
device, NULL, NULL, NULL, 0, NULL, NULL)) {
|
||||
if (link->match_name && !strv_contains(link->match_name, "*")) {
|
||||
unsigned name_assign_type = NET_NAME_UNKNOWN;
|
||||
|
||||
|
@ -458,6 +459,10 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
|
|||
if (r < 0)
|
||||
return log_warning_errno(r, "Could not set Alias=, MACAddress= or MTU= on %s: %m", old_name);
|
||||
|
||||
r = rtnl_set_link_alternative_names(&ctx->rtnl, ifindex, config->alternative_names);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Could not set AlternativeName= on %s: %m", old_name);
|
||||
|
||||
*name = new_name;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -48,6 +48,7 @@ struct link_config {
|
|||
MACAddressPolicy mac_address_policy;
|
||||
NamePolicy *name_policy;
|
||||
char *name;
|
||||
char **alternative_names;
|
||||
char *alias;
|
||||
uint32_t mtu;
|
||||
size_t speed;
|
||||
|
|
|
@ -51,7 +51,7 @@ TEST_NO_NSPAWN=1
|
|||
Don't run tests under systemd-nspawn
|
||||
|
||||
TEST_NO_KVM=1
|
||||
Disable QEMU KVM autodetection (may be necessary when you're trying to run the
|
||||
Disable QEMU KVM auto-detection (may be necessary when you're trying to run the
|
||||
*vanilla* QEMU and have both qemu and qemu-kvm installed)
|
||||
|
||||
TEST_NESTED_KVM=1
|
||||
|
|
|
@ -16,6 +16,7 @@ MACAddressPolicy=
|
|||
MACAddress=
|
||||
NamePolicy=
|
||||
Name=
|
||||
AlternativeName=
|
||||
Alias=
|
||||
MTUBytes=
|
||||
BitsPerSecond=
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[Match]
|
||||
OriginalName=dummy98
|
||||
|
||||
[Link]
|
||||
AlternativeName=hogehogehogehogehogehoge
|
|
@ -14,6 +14,7 @@ Name=ifb99
|
|||
Name=ipiptun99
|
||||
Name=nlmon99
|
||||
Name=xfrm99
|
||||
Name=hogehogehogehogehogehoge
|
||||
|
||||
[Network]
|
||||
LinkLocalAddressing=yes
|
||||
|
|
|
@ -127,6 +127,17 @@ def expectedFailureIfNexthopIsNotAvailable():
|
|||
|
||||
return f
|
||||
|
||||
def expectedFailureIfAlternativeNameIsNotAvailable():
|
||||
def f(func):
|
||||
call('ip link add dummy98 type dummy', stderr=subprocess.DEVNULL)
|
||||
rc = call('ip link prop add dev dummy98 altname hogehogehogehogehoge', stderr=subprocess.DEVNULL)
|
||||
if rc == 0:
|
||||
return func
|
||||
else:
|
||||
return unittest.expectedFailure(func)
|
||||
|
||||
return f
|
||||
|
||||
def setUpModule():
|
||||
global running_units
|
||||
|
||||
|
@ -425,6 +436,7 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
|||
'11-dummy-mtu.netdev',
|
||||
'11-dummy.network',
|
||||
'12-dummy.netdev',
|
||||
'12-dummy.link',
|
||||
'25-address-static.network',
|
||||
'25-veth.netdev',
|
||||
'netdev-link-local-addressing-yes.network',
|
||||
|
@ -439,6 +451,16 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
|||
remove_unit_from_networkd_path(self.units)
|
||||
stop_networkd(show_logs=True)
|
||||
|
||||
@expectedFailureIfAlternativeNameIsNotAvailable()
|
||||
def test_altname(self):
|
||||
copy_unit_to_networkd_unit_path('netdev-link-local-addressing-yes.network', '12-dummy.netdev', '12-dummy.link')
|
||||
check_output('udevadm control --reload')
|
||||
start_networkd()
|
||||
self.wait_online(['dummy98:degraded'])
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'dummy98', env=env)
|
||||
self.assertRegex(output, 'hogehogehogehogehogehoge')
|
||||
|
||||
def test_reconfigure(self):
|
||||
copy_unit_to_networkd_unit_path('25-address-static.network', '12-dummy.netdev')
|
||||
start_networkd()
|
||||
|
@ -529,11 +551,11 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
|||
start_networkd()
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1')
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'Type: ether')
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'lo')
|
||||
output = check_output(*networkctl_cmd, 'status', 'lo', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'Type: loopback')
|
||||
|
||||
|
@ -543,12 +565,12 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
|||
start_networkd()
|
||||
self.wait_online(['test1:degraded'])
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1')
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
|
||||
self.assertRegex(output, r'Network File: /run/systemd/network/11-dummy.network')
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'lo')
|
||||
output = check_output(*networkctl_cmd, 'status', 'lo', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, r'Link File: (/usr)?/lib/systemd/network/99-default.link')
|
||||
self.assertRegex(output, r'Network File: n/a')
|
||||
|
@ -560,7 +582,7 @@ class NetworkctlTests(unittest.TestCase, Utilities):
|
|||
|
||||
self.wait_online(['test1:degraded', 'veth99:degraded', 'veth-peer:degraded'])
|
||||
|
||||
check_output(*networkctl_cmd, 'delete', 'test1', 'veth99')
|
||||
check_output(*networkctl_cmd, 'delete', 'test1', 'veth99', env=env)
|
||||
self.assertFalse(link_exists('test1'))
|
||||
self.assertFalse(link_exists('veth99'))
|
||||
self.assertFalse(link_exists('veth-peer'))
|
||||
|
@ -805,7 +827,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
|||
self.assertEqual(1, int(read_link_attr('bridge99', 'bridge', 'stp_state')))
|
||||
self.assertEqual(3, int(read_link_attr('bridge99', 'bridge', 'multicast_igmp_version')))
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'bridge99')
|
||||
output = check_output(*networkctl_cmd, 'status', 'bridge99', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'Priority: 9')
|
||||
self.assertRegex(output, 'STP: yes')
|
||||
|
@ -1372,7 +1394,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
|
|||
self.assertRegex(output, '00:11:22:33:44:66 dst 10.0.0.6 self permanent')
|
||||
self.assertRegex(output, '00:11:22:33:44:77 dst 10.0.0.7 self permanent')
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'vxlan99')
|
||||
output = check_output(*networkctl_cmd, 'status', 'vxlan99', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, 'VNI: 999')
|
||||
self.assertRegex(output, 'Destination Port: 5555')
|
||||
|
@ -1643,7 +1665,7 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
|
|||
start_networkd()
|
||||
self.wait_online(['test1:routable'])
|
||||
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1')
|
||||
output = check_output(*networkctl_cmd, 'status', 'test1', env=env)
|
||||
print(output)
|
||||
self.assertRegex(output, '192.168.0.15')
|
||||
self.assertRegex(output, '192.168.0.1')
|
||||
|
|
Loading…
Reference in New Issue