We added "ipv4.route-table-sync" and "ipv6.route-table-sync" to not change
behavior for users that configured policy routing outside of NetworkManager,
for example, via a dispatcher script. Users had to explicitly opt-in
for NetworkManager to fully manage all routing tables.
These settings were awkward. Replace them with new settings "ipv4.route-table"
and "ipv6.route-table". Note that this commit breaks API/ABI on the unstable
development branch by removing recently added API.
As before, a connection will have no route-table set by default. This
has the meaning that policy-routing is not enabled and only the main table
will be fully synced. Once the user sets a table, we recognize that and
NetworkManager manages all routing tables.
The new route-table setting has other important uses: analog to
"ipv4.route-metric", it is the default that applies to all routes.
Currently it only works for static routes, not DHCP, SLAAC,
default-route, etc. That will be implemented later.
For static routes, each route still can explicitly set a table, and
overwrite the per-connection setting in "ipv4.route-table" and
"ipv6.route-table".
Expose previously internal function nm_ip_route_equal_full(). It's
just useful API.
However, add a @cmp_flags argument, so that in the future we could
extend it.
For kernel and NetworkManager's core, route identity is a complicated topic
(see NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID). For example, a route
without explity table is treated identical to "table 254" or "table 0".
It would be complicated to have nm_setting_ip_config_add_route()
implement that logic, especially since libnm offers not public API
to expose kernel's logic.
However, previously nm_setting_ip_config_add_route() would only consider
dest/prefix,next_hop,metric when comparing for equality. Hence, with
nmcli connection modify "$CON" +ipv4.routes '192.168.5.0/24'
nmcli connection modify "$CON" +ipv4.routes '192.168.5.0/24 table=42'
the second route was not actually added, although it is a very different
route. Fix that, and consider attributes too. Note that this allows the user
to add two routes that look different to libnm, but are actually idential:
nmcli connection modify "$CON" +ipv4.routes '192.168.5.0/24'
nmcli connection modify "$CON" +ipv4.routes '192.168.5.0/24 table=254'
In the above example, the route instances look different, but
sementically they are both the same route in the main table (254).
This also allows the user to add routes that are semantically different, but
are treated as the same route by kernel:
nmcli connection modify "$CON" +ipv6.routes 'a🅱️c::/120'
nmcli connection modify "$CON" +ipv6.routes 'a🅱️c::/120 mtu=600'
I think libnm should allow to add routes as long as they look different
to libnm. Regardless how kernel and NetworkManager-core thinks about
route identity.
This changes API of nm_setting_ip_config_add_route(). However, I think
the previous behavior was just broken.
Same for nm_setting_ip_config_remove_route_by_value().
GArray's and GPtrArray's plen argument is unsigned. The index variable
to iterate the list, should not have a smaller range (or different data type).
Also, assert against negative idx argument.
The previous parsing was done using regex. One could implement a
complex regex to parse the setting. However, as it was implemented,
the regex would just pick out parts of the line that it expects,
and ignore unknown parts.
Let's be strict about what we parse. The only strong requirement
is that NM can parse everything that was written by NM itself.
Eventually, we could extend the parser to accept everything that
initscripts accept.
Initscripts split the line at $IFS and do filename globbing on the
arguments. That is ugly, because globbing is of coures wrong (we don't
do that). But also, the splitting at $IFS cannot be escaped, hence for
initscripts it is impossible to use '<space><tab><newline>'. We do that
too, as it makes it easy to parse. Later we may want to extend this to
allow a form of escaping/quoting.
Yes, we may now ignore routes that are not defined as we expect them.
- kernel ignores rtm_tos for IPv6 routes. While iproute2 accepts it,
let libnm reject TOS attribute for routes as well.
- move the tos field from NMPlatformIPRoute to NMPlatformIP4Route.
- the tos field is part of the weak-id of an IPv4 route. Meaning,
`ip route add` can add routes that only differ by their TOS.
This adds definition of a set of known route option attributes to
libnm-core and helper functions.
nm_ip_route_attribute_validate() performs the validation of the
attribute type and, in case of a formatted string attribute, of its
content.
nm_ip_route_get_variant_attribute_spec() returns the attribute format
specifier to be passed to nm_utils_parse_variant_attributes(). Since
at the moment NMIPRoute is the only user of NMVariantAttributeSpec and
the type is opaque to users of the library, the struct is extended to
carry some other data useful for validation.
Backported symbols only make sense for libnm itself, not for
libnm-core which is statically linked with NetworkManager and
nm-ifcace-helper. Declaring the symbols in libnm-core, means
that NetworkManager binary also contains them, although there
are not used.
Move them to libnm.
When comparing settings, nm_setting_compare() performs a complicated
logic, which basically serializes each GObject property to a GVariant
for the D-Bus representation.
That is wrong for example for ipv4.addresses, which don't contain
address labels. That is, the GObject property is called "addresses",
but the D-Bus field "addresses" cannot encode every information
and thus comparison fails. Instead, it would have to look into
"address-data".
Traditionally, we have virtual functions like compare_property() per
NMSetting to do the comparison. That comparison is based on the GObject
properties. I think that is wrong, because we should have a generic
concept of what a property is, independent from GObject properties.
With libnm, we added NMSettingProperty, which indeed is such an
GObject independent representation to define properties.
However, it is not used thoroughly, instead compare_property() is a hack
of special cases, overloads from NMSettingProperty, overloads of
compare_property(), and default behavior based on GParamSpec.
This should be cleaned up.
For now, just hack it by handle the properties with the problems
explicitly.
Commit bdd0e7fec0 which added symbol
nm_setting_ip_config_get_dns_priority to libnm_1_4_0 was backported
to nm-1-2 in commit ad1cdcf6571da23e3197b09f1b4b14d23b8899d1.
Add the backported symbol to master to allow seemless upgrading
from 1.2.4 to 1.4.0.
Having a gateway defined when never-default=yes causes troubles in
connection matching and anyway makes no sense.
If the combination is found, remove the gateway during the
normalization phase.
https://bugzilla.redhat.com/show_bug.cgi?id=1313091
Adding addresses with a prefix of zero is valid. Don't
reject them.
Note that this is an actual bug. If you configure an
address with prefix length zero, nmcli will report:
$nmcli connection
(process:1040): libnm-WARNING **: Ignoring invalid IP4 address: Invalid IPv4 address prefix '0'
In some situations, we want strict checking of errors, for example when
NetworkManager receives a new connection from a client, the connection
must make sense as a whole (and since NetworkManager service is backward
compatible to the clients and not the other way around, there is no
excuse for sending invalid data to the server).
In other situations, we want a best-effort behavior. Like when
NetworkManager sends a connection to its clients, those clients
want to extract as many properties as they understand, but in order
to be forward compatible against newer server versions, invalid
or unknown properties must be accepted.
Previously, a mixture of both was done. Some issues caused a failure
to create a new NMSetting, other invalid parts were just silently
ignored or triggered a g_warning() in glib.
Now allow for both. When doing strict-validation, be more strict and
reject all unknown properties and catch when the user sets an invalid
argument. On the other hand, allow for a best-effort mode that
effectively cannot fail and will return a new NMSetting instance.
For now, add NMSettingParseFlags so that the caller can choose the
old behavior, strict parsing, or best effort.
This patch doesn't have any externally visible change except that
no more g_warnings will be emitted.
- All internal source files (except "examples", which are not internal)
should include "config.h" first. As also all internal source
files should include "nm-default.h", let "config.h" be included
by "nm-default.h" and include "nm-default.h" as first in every
source file.
We already wanted to include "nm-default.h" before other headers
because it might contains some fixes (like "nm-glib.h" compatibility)
that is required first.
- After including "nm-default.h", we optinally allow for including the
corresponding header file for the source file at hand. The idea
is to ensure that each header file is self contained.
- Don't include "config.h" or "nm-default.h" in any header file
(except "nm-sd-adapt.h"). Public headers anyway must not include
these headers, and internal headers are never included after
"nm-default.h", as of the first previous point.
- Include all internal headers with quotes instead of angle brackets.
In practice it doesn't matter, because in our public headers we must
include other headers with angle brackets. As we use our public
headers also to compile our interal source files, effectively the
result must be the same. Still do it for consistency.
- Except for <config.h> itself. Include it with angle brackets as suggested by
https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers
Change the dhcp-timeout property in NMSettingIPConfig to int type for
consistency with the dad-timeout property. For dad-timeout -1 means
"use default value", while for dhcp-timeout probably we will never use
negative values, but it seems more correct to use the same type for
the two properties.
The property is used to control duplicate address detection:
* -1 means default value
* 0 means no DAD is performed
* > 0 means timeout (in milliseconds) for arping responses
[bgalvani: moved setting from NMSettingIP4Config]
The property contains the fully qualified domain name to be sent to
DHCP server using the FQDN option. The property is mutually exclusive
with 'dhcp-hostname'.
Otherwise the callers would free the address and it would result in
double-free.
Ideally, the function would return const pointer, but changing it now
would require changing also other prototypes and much code due to
snowball effect of const.
https://bugzilla.gnome.org/show_bug.cgi?id=756380
The localization headers are now included via "nm-default.h".
Also fixes several places, where we wrongly included <glib/gi18n-lib.h>
instead of <glib/gi18n.h>. For example under "clients/" directory.
Rather than randomly including one or more of <glib.h>,
<glib-object.h>, and <gio/gio.h> everywhere (and forgetting to include
"nm-glib-compat.h" most of the time), rename nm-glib-compat.h to
nm-glib.h, include <gio/gio.h> from there, and then change all .c
files in NM to include "nm-glib.h" rather than including the glib
headers directly.
(Public headers files still have to include the real glib headers,
since nm-glib.h isn't installed...)
Also, remove glib includes from header files that are already
including a base object header file (which must itself already include
the glib headers).
Remove an assertion in canonicalize_ip() to assert that either a
non-NULL @ip is given, or @null_any is TRUE.
The condition of the assert is not easy to understand without context.
Instead the caller should already handle %NULL properly.
All callers that pass @null_any=FALSE to canonicalize_ip(), already assert
that the argument is not %NULL. With the exception of nm_ip_route_new()
which however checks for a valid @dest early on.
We call valid_ip() from nm_ip_route_new() to check whether an untrusted string
is a valid ip address. Properly handle %NULL argument.
Fixes: 21c8a6b20e