Currently libnm headers include <linux/if_{ether,infiniband,vlan}.h>.
These are public headers, that means we drag in the linux header to all
users of <NetworkManager.h>.
Often the linux headers work badly together with certain headers from libc.
Depending on the libc version, you have to order linux headers in the right
order with respect to libc headers.
We should do better about libnm headers. As a first step, assume that
the linux headers don't get included by libnm, and explicitly include
them where they are needed.
The parser checks if the first token of an ip= argument is an IP
address to determine which of the two possible syntaxes is used:
ip=<interface>:{dhcp|on|any|dhcp6|auto6}[:[<mtu>][:<macaddr>]]
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}[:[<mtu>][:<macaddr>]]
This works as long as the first token is not empty, which - according
to the dracut.cmdline man page - seems to be guaranteed.
However, the network-legacy dracut plugin accepts an empty interface
or client IP. Also, if a user needs DHCP and wants to specify a
hostname, the only possible syntax is:
ip=::::<hostname>::dhcp
Change the parser to check the second token instead, similarly to what
the network-legacy module does [1].
[1] https://github.com/dracutdevs/dracut/blob/050/modules.d/40network/net-lib.sh#L490https://bugzilla.redhat.com/show_bug.cgi?id=1900260https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/693
Change the generator to disable by default IP configuration for the
parent connection of a VLAN, because that is what a user would expect
and what the legacy module does. Of course if the user explicitly
configures DHCP or an address for the parent interface, that overrides
the default.
Note that now the generator always creates a connection for the parent
interface. Before this commit, it did only when there was an explicit
ip= argument for the parent interface.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/509
The command line parser looks for a dot or a colon to determine
whether the first token in a ip= argument is a IPv4 address (dot), an
IPv6 address (colon) or an interface name (none). This strategy
doesn't work for interface names containing a dot (typically VLANs).
Instead, try to parse the IPv4/IPv6 address in the token; if this
fails then consider the token as an interface name.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/581
For historic reasons is NMSettingBond implemented differently from other
settings. It uses a strdict, and adds some validation on top of that.
The idea was probably to be able to treat bond options more generically.
But in practice we cannot treat them as opaque values, but need to know,
validate and understand all the options. Thus, this implementation with a
strdict is not nice.
The user can set the GObject property NM_SETTING_BOND_OPTIONS to any
strdict, and the setter performs no validation or normalization. That
is probably good, because g_object_set() cannot return an error to
signalize invalid settings. As often, we have corresponding C API like
nm_setting_bond_add_option() and nm_setting_bond_remove_option(). It
should be possible to get the same result both with the C API and with
the GObject property setting. Since there is already a way to set
certain invalid values, it does not help if the C API tries to prevent
that. That implies, that also add-option does not perform additional
validation and sets whatever the user asks.
Remove all validation from nm_setting_bond_add_option() and
nm_setting_bond_remove_option(). This validation was anyway only very
basic. It was calling nm_setting_bond_validate_option(), which can check
whether the string is (for example) and integer, but it cannot do
validation beyond one option. In most cases, the validation needs to
take into account the bond mode or other options, so validating one
option in isolation is not very useful.
Proper validation should instead be done via nm_connection_verify().
However, due to another historic oddity, that verification is very
forgiving too and doesn't reject many invalid settings when it should.
That is hard to fix, because making validation more strict can break
existing (and working) configurations. However, verify() already contains
basic validation via nm_setting_bond_validate_option(). So in the previous
behavior nm_setting_bond_add_option() would silently do nothing (only
returning %FALSE) for invalid options, while now it would add the
invalid options to the dictionary -- only to have it later fail validation
during nm_connection_verify(). That is a slight change in behavior, however it
seems preferable.
It seems preferable and acceptable because most users that call
nm_setting_bond_add_option() already understand the meaning and valid
values. Keyfile and ifcfg-rh readers are the few exceptions, which really just
parse a string dictionary, without need to understand them. But nmtui
or nmstate already know the option they want to set. They don't expect
a failure there, nor do they need the validation.
Note that this change in behavior could be dangerous for example for the
keyfile/ifcfg-rh readers, which silently ignored errors before. We
don't want them to start failing if they read invalid options from a
file, so instead let those callers explicitly pre-validate the value
and log an warning.
https://bugzilla.redhat.com/show_bug.cgi?id=1887523
This is potentially a breaking change, formerly speciyfing 'none|off'
in the kernel cmdline option 'ip' was understood by the dracut
network-module as doing 'ipv6.method=auto' which is clearly incosistent
with the 'off' naming, thus 'off|none' now means to actually disable
both ipv6 and ipv4 (unless a static ip is provided).
Unit test added.
https://bugzilla.redhat.com/show_bug.cgi?id=1883958
Reverts: 440a0b4078 ('initrd: set ipv6.method=auto when the autoconfiguration field is 'none'')
Signed-off-by: Antonio Cardace <acardace@redhat.com>
Run:
./contrib/scripts/nm-code-format.sh -i
./contrib/scripts/nm-code-format.sh -i
Yes, it needs to run twice because the first run doesn't yet produce the
final result.
Signed-off-by: Antonio Cardace <acardace@redhat.com>
Since commit 3df662f534 ('settings: rework wait-device-timeout
handling and consider device compatibility'), "connection.wait-device-timeout"
works with profiles in general and doesn't require an interface-name
set.
Remove that restriction and let initrd generator create profiles that
always wait.
The network-legacy dracut module waits for all ethernet devices if the
command line contains rd.neednet=1. It also waits for the device
specified by 'bootdev='.
Do the same.
https://bugzilla.redhat.com/show_bug.cgi?id=1853348
When a 'ip=auto6' option is passed to kernel, the old dracut network
module only sets accept_ra in kernel and wait for the address to
appear. Instead, with a 'ip=dhcp6' option it starts 'dhclient -6',
leaving accept_ra to the initial value (that is already 1). So
'ip=dhcp6' in practice does kernel IPv6 autoconf and DHCPv6 at the
same time, without honoring the 'Managed' flag of the router
advertisement.
It seems that the only reason to have distinct 'auto6' and 'dhcp6'
options was that network module did not support starting DHCPv6 only
when necessary based on the M flag of the RA; so the user had to
specify if DHCPv6 was needed or not.
Given that 1) NM is smarter and can start DHCPv6 only when needed by
RA; 2) DHCPv6 alone only gets a /128 address without a prefix route
and so it's not useful; then it makes sense to generate a connection
with 'ipv6.method=auto' for both 'ip=auto6' and 'ip=dhcp6'.
https://bugzilla.redhat.com/show_bug.cgi?id=1854323https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/571
(cherry picked from commit ca3d0a8f06)
There is a bug when parsing a BOOTIF= without any existing
connection. The generated connection doesn't have wired setting and
later we try to access it:
# nm-initrd-generator --stdout -- BOOTIF=01-50-50-00-9f-21-21
(nm-initrd-generator:1546): libnm-CRITICAL **: ((libnm-core/nm-setting-wired.c:205)): assertion '<dropped>' failed
(nm-initrd-generator:1546): GLib-GObject-CRITICAL **: g_object_set: assertion 'G_IS_OBJECT (object)' failed
Fix this.
https://bugzilla.redhat.com/show_bug.cgi?id=1853277
Fixes: 25a2b6e14f ('initrd: rework command line parsing')
(cherry picked from commit 3023c70e4e)
Setting a MTU or a cloned MAC for bonds/bridges/teams fails with:
# nm-initrd-generator -- bond=bond0:eno1,eno2:mode=802.3ad
ip=192.168.1.5::192.168.1.254:255.255.255.0:MyServer:bond0:none::01:02:03:04:05:06
bootdev=bond0 nameserver=192.168.1.1
<warn> cmdline-reader: 'bond' does not support setting cloned-mac-address
Fix this.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/460
(cherry picked from commit 79f70bf5d6)
The 7th field of:
ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}:[:[<mtu>][:<macaddr>]]
specifies which kind of autoconfiguration to do. 'none' and 'off' mean
static addresses.
The old network module of dracut used to leave kernel IPv6
autoconfiguration enabled when IPv4 static addresses were
configured. With NM, this corresponds to enabling IPv6 auto method.
https://bugzilla.redhat.com/show_bug.cgi?id=1848943
(cherry picked from commit a39eb9ac14)
When the initrd generator creates a connection with IPv6 method
'ignore', the kernel will do IPv6 autoconfiguration on the
interface. However, it is preferable to let NetworkManager configure
the interface directly instead of relying on kernel. Therefore, change
the IPv6 method to 'auto'. Note that we still set ipv6.may-fail to
'yes' so that a failure during IPv6 autoconfiguration doesn't bring
down the interface.
(cherry picked from commit f6d654b18f)
Code like
»···»···if (strcmp (tag, "net.ifnames") == 0)
»···»···»···net_ifnames = strcmp (argument, "0") != 0;
is really hard to understand (at least to me). Compare to
»···»···if (nm_streq (tag, "net.ifnames"))
»···»···»···net_ifnames = !nm_streq (argument, "0");
g_ascii_strtoull() returns a guint64, which is very wrong to directly pass
to the variadic argument list of g_object_set(). We expect a guint there
and need to cast.
While at it, use _nm_utils_ascii_str_to_int64() to parse and validate the input.
$ meson -Dmore_asserts=0 meson-build
$ ninja -C meson-build
[712/859] Compiling C object 'src/initrd/b383957@@nmi-core@sta/nmi-cmdline-reader.c.o'.
../src/initrd/nmi-cmdline-reader.c: In function ‘nmi_cmdline_reader_parse’:
../src/initrd/nmi-cmdline-reader.c:871:4: warning: ‘s_ip’ may be used uninitialized in this function [-Wmaybe-uninitialized]
871 | nm_setting_ip_config_add_dns (s_ip, ns);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../src/initrd/nmi-cmdline-reader.c:835:21: note: ‘s_ip’ was declared here
835 | NMSettingIPConfig *s_ip;
| ^~~~
Fixes: 25a2b6e14f ('initrd: rework command line parsing')
The 'default_connection' created by the command line parser has
multiple purposes. It's the connection created for 'ip=' arguments
without command line, but is also created when there is a 'bootdev='
or for 'nameserver=' and no other connection exists at the moment the
argument is parsed. This is confusing and leads to a result that
depends on the order of parameters. For example:
$ /usr/libexec/nm-initrd-generator -c connections -- bootdev=eth1 ip=eth0:dhcp
$ ls connections/
default_connection.nmconnection eth0.nmconnection
$ /usr/libexec/nm-initrd-generator -c connections -- ip=eth0:dhcp bootdev=eth1
$ ls connections/
eth0.nmconnection eth1.nmconnection
Make this more explicit by tracking 'bootdev_connection' and
'default_connection' individually.
Also fix handling of 'nameserver', 'rd.peerdns' and 'rd.route'
arguments. First process all connections, and then set those
properties. In particular, now nameservers are applied to all
connections.
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/issues/391
Connections are kept in a hash table indexed by name. This causes non
deterministic output in get_conn() when we have to decide a default
connection and no bootdev was specified on the command line.
Also add an array that stores the original order in which interfaces
appear in the command line, and use it when we have to loop through
connections. The return value of nmi_cmdline_reader_parse() is still a
hash table because once we have generated connections, their order
doesn't matter.
Don't add an empty connection to the list if
nmi_ibft_update_connection_from_nic() fails when reading iBFT
information.
If the function fails in parse_ip(), continue with the existing
connection built from other command line options.
Also, fix a memory leak.
In all the cases, we don't want to perform locale dependent comparison.
$ sed -i 's/\<strcasecmp\>/g_ascii_\0/g' $(git grep -w -l strcasecmp -- ':(exclude)shared/systemd/' )
We should use the same "is-valid" function everywhere.
Since nm_utils_ipaddr_valid() is part of libnm, it does not qualify.
Use nm_utils_ipaddr_is_valid() instead.
Do process the connections from the iBFT block if the rd.iscsi.ibft or
rd.iscsi.ibft=1 argument is present.
This is supposed to fix what was originally reported by Kairui Song
<kasong@redhat.com> here: https://github.com/dracutdevs/dracut/pull/697
It is really not clear what the user could have meant by specifying a
bootdev= argument, and we deal with it just by ensuring a device with
that name whould come up.
We therefore pick a default connection if there's one (that is a
conneciton that we create if the device name is unspecified, as in
"ip=auto"), otherwise we create a new one.
When processing the rd.znet option set the interface name only in case when
the persistent interface names feature isn't disabled via net.ifnames=0
[lkundrak@v3.sk: minor tweaks to the net.ifnames=0 parsing]
The current solution for s390 specific details relies on an interface to
exist before adding the s390 details. It means the ip= option must precede
the rd.znet= option. Also only a single interface can be configured. With
this change the s390 details are put to the right interface and properly
named interface is created if it hasn't existed yet.
While nmi_cmdline_reader_parse() only has one caller, which indeed has the
argv parameter at hand and doesn't care it to be modified, I think it
is ugly.
Arguments preferably are strictly either input or output arguments,
with input arguments not being modified by the call.
- nm_setting_wired_add_s390_option() asserts that a "value" argument
is given. Check that the string contains a '=' where we can split.
- pass the requested NM_SETTING_WIRED_SETTING_NAME type to get_conn().
Otherwise, @s_wired might be %NULL, resulting in an assertion.
I do wonder whether this always retrieves a connection of the
appropriate type for modification, or whether a profile could
be returned that was created for a different purpose. But that
isn't changed.
- avoid "g_strcmp0 (nettype, "ctc") != 0". I find it unexpected, that we add the
3rd subchannel component, if the nettype is "ctc" (intuitively, I'd expect it
to be the opposite). The reasons for this are not documented, but I
presume it is correct.
Anyway, using streq() makes this slightly more clear to me, as with
strcmp() I would wonder whether this was just a typo while with
streq() I'd be more confident that this is indeed intended.
- don't initialize local variables unnecessarily. The compiler would
warn if we would forget about this. Also, don'\''t use { } for a
one-line block.