The return value of g_hash_table_add() was added in GLib 2.40, use the
wrapper to avoid compile error on older versions:
src/nm-policy.c: In function ‘auto_activate_device’:
src/nm-policy.c:1279:7: error: void value not ignored as it ought to be
Fixes: a1ea422aad
When a connection is autoactivated NMPolicy only detects a failure by
watching the device state, or when the activation fails immediately.
If the activation fails after the asynchronus authorization check
before the device enters the PREPARE state, no other connection is
tried.
Let NMPolicy watch the active-connection state to detect early
failures and disconnect the signal handler when we detect that the
device state is progressing.
https://bugzilla.redhat.com/show_bug.cgi?id=1310676
Whenever we call a platform operation that reads or writes the netlink
socket, there is the possibility that the cache gets updated, as we
receive netlink events.
It is thus racy, if nm_platform_ip_route_sync() *first* adds routes, and
then obtains a list of routes to delete. The correct approach is to
determine which routes to delete first (and keep it in a list
@routes_prune), and pass that list down to nm_platform_ip_route_sync().
Arguably, this doesn't yet solve every race. For example, NMDevice
calls update_ext_ip_config() during ip4_config_merge_and_apply().
That is good, as it resyncs with platform. However, before calling
nm_ip4_config_commit() it calls other platform operations, like
_commit_mtu(). So, the race is still there.
Since commit a21b8882cc ("device: update
external configuration before commit"), we correctly re-sync the
external IP configuration before a merge, in case we notice that
there were some changes in platform.
Go a step further, and do the full update_ext_ip_config(). We should
have one way how to capture the external config, including intersect
and subtract. Otherwise, we end up with an @ext_ip4_config, which is
different from how it looks usually.
Refactor the code. There should be no changes in behavior at all.
The point is, to be able to reuse update_ext_ip_config() in the
next commit.
And also, I think it's an antipattern to have mirroring functions like
ip4_xyz() and ip6_xyz(). Instead, there should be one function, with
extra addr_family argument. That way, it'much clearer where two
implementations differ and where they are identical.
Basically, it moves the differentiation per the address family down
the call stack, closer to the place where the behavior is actually
different.
Kernel does not allow to add a route with table 0 (RT_TABLE_UNSPEC). It
effectively is an alias for the main table. We must consider that when
comparing routes sementically.
If the commit of static connection parameters fails before starting
RA, we should reset @con_ip6_config; otherwise any external update
arriving before the commit of RA parameters will remove from
@con_ip6_config all parameters not present externally, because in
update_ip6_config() we do:
/* This function was called upon external changes. Remove the configuration
* (addresses,routes) that is no longer present externally from the internal
* config. This way, we don't re-add addresses that were manually removed
* by the user. */
if (priv->con_ip6_config)
nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config);
Instead if @con_ip6_config is cleared it will be rebuilt from the
connection setting at the next commit.
Fixes-test: @ipv6_preserve_cached_routes
No need for duplicate log lines
<debug> [1506146476.8462] platform: link: adding tap tap0 owner 107 group -1
<debug> [1506146476.8462] platform-linux: link: add tap tap0 owner 107 group -1
Merge them.
Also, for consistency change the logging output for adding generic
interfaces in nm_platform_link_add().
When a device managed by NetworkManager is configured manually (adding
ip addresses), NetworkManager will track the device configuration with
an in-memory only config, marking the device as "external".
Devices marked external should be just tracked but left untouched.
This does not happens on current code base: if an ipv4 address is added,
NM generates the in-memory connection, marking the ipv6.method as "ignore".
While activating the connection, NM will process the IPv6 "ignore" method:
this implies leaving the IPv6LL address generation to the kernel. To
trigger this NM will disable/enable IPv6 on the interface.
This not only may change the device configuration but may cause also
a potential race with an external IPv6 assignment on the device.
NetworkManager should do nothing to IPv6 when method is "ignore" and
connection is marked as "external": this commit fixes this behavior.
Note that if/once an IPv6 address is externally added, IPv6 method in the
tracked connection is changed to "manual" and a link local address will be
generated if needed.
https://bugzilla.redhat.com/show_bug.cgi?id=1462260
CC src/devices/src_libNetworkManager_la-nm-device.lo
In file included from src/devices/nm-device.c:45:0:
src/devices/nm-device.c: In function ‘_v4_has_shadowed_routes_detect’:
./src/platform/nmp-object.h:400:54: error: ‘o’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
_obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip4_route : NULL; \
^
src/devices/nm-device.c:2774:19: note: ‘o’ was declared here
const NMPObject *o;
^
At startup the manager tries to create virtual devices without a
specific order and spits warnings when a device can't be realized
because the parent device is not yet created. These failures are not
something the user should worry about because the creation will be
retried when the parent appears.
A better approach is to return an error code from the device's
create_and_realize() telling that it failed because the parent doesn't
exist. In this way, the manager knows that the device isn't ready and
can avoid printing warning messages.
After a device is created in system_create_virtual_device(), the
manager tries to activate connections that depend on the device
even if the device isn't realized, as in the following log:
# team0 gets created
<info> manager: (team0): new Team device (/org/freedesktop/NetworkManager/Devices/7)
# team0.23 gets created
<debug> device[0x28079b0] (team0.23): constructed (NMDeviceVlan)
<debug> manager: (team0-vlan23) create virtual device team0.23
<debug> device[0x28079b0] (team0.23): unmanaged: flags set to [platform-init,!sleeping=0x10/0x11/unmanaged/unrealized], set-managed [sleeping
<info> manager: (team0.23): new VLAN device (/org/freedesktop/NetworkManager/Devices/8)
# the manager tries to realize team0.23
<debug> device[0x28079b0] (team0.23): create (is nm-owned)
<warn> manager: (team0-vlan23) couldn't create the device: cannot retrieve ifindex of interface team0 (Team): skip VLAN creation for now
<debug> manager: (team0.23): removing device (allow_unmanage 1, managed 0)
<debug> device[0x28079b0] (team0.23): ip4-config: update (commit=0, new-config=(nil))
<debug> device[0x28079b0] (team0.23): ip6-config: update (commit=0, new-config=(nil))
<debug> device[0x28079b0] (team0.23): disposing
<debug> device[0x28079b0] (team0.23): ip4-config: update (commit=1, new-config=(nil))
<debug> device[0x28079b0] (team0.23): ip6-config: update (commit=1, new-config=(nil))
<debug> device[0x28079b0] (team0.23): finalize(): NMDeviceVlan
# the manager realizes team0
<debug> device[0x2800870] (team0): create (is nm-owned)
<debug> platform: link: add link 'team0' of type 'team' (196610)
Change the order of operations and try the child connection only after
the parent has been realized.
Before commit 6698bf58bb, we would rely on
kernel to add the device-route for manual IPv6 routes. We broke that and now
kernel would still add the device-route, however nm_platform_ip_route_sync()
would delete it immediately after.
That is because previously nm_platform_ip_route_sync() would ignore routes
with rtm_protocol RTPRO_KERNEL. Now, it will sync and delete those too.
Fix that by adding the device-route like we do it for IPv4. This also
fixes an actual issue where the automatically added route always had
route-metric 256. Instead, we now use the metric from ipv6.route-metric
setting.
Fixes: 6698bf58bb
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.
svGetValueStr() is preferred over svGetValueStr_cp() because it may safe
an additional string copy (if the value needs no unescaping/unquoting).
Also, use nm_utils_strsplit_set() because it saves to copy each word.
There are some changes here. For example, read_8021x_list_value()
previously would not strip empty words. When switching from
g_strsplit_set() to nm_utils_strsplit_set(), empty words are implicitly
skipped.
If we don't commit the IP config, we must merge the currently tracked
default route. Otherwise, on every non-commit call of
ip4_config_merge_and_apply(), the default-route gets lost.
Fixes: 77ec302714
Kernel does not allow to add IPv6 routes with "src", as long as the
corresponding address is still tentative (related bug rh#1457196).
The workaround for this is cumbersome. First, when we fail to add such a
route with "pref_src", we guess that it happend due to this issue. In
that case, nm_ip6_config_commit() returns the list of routes that could
not be added for the moment (but hopefully can be added later).
We track this list in NMDevice, and keep trying to merge the routes
back into ip6_config. In order to not try indefinitely, keep track of a
timestamp when we tried to add this route for the first time.
Another uglyness is that pending tentative routes don't explicitly block
activation. In practice they may do, because for these routes we also have
an IPv6 address that is still doing DAD, so the IP configuration is
still pending due to that.
https://bugzilla.redhat.com/show_bug.cgi?id=1452684
the --timeout command line option is a custom feature added in some
linux distributions (fedora). Passing that command line argument will
make dhclient fail if the binary does not support it, preventing
activation of dhcp based connections.
Worse, the option has just been recently changed from "-timeout", so
that we are currently incompatibile with Centos, RedHat and older
versions of Fedora too.
Leverage the "timeout" option in dhclient config file: it will produce
the expected behavior and will be universally supported.
Fixes test: dhcp-timeout
Fixes: fa46736013https://bugzilla.redhat.com/show_bug.cgi?id=1491243
Let's not treat those routes special. I think this was originally done, because
we relied on kernel to add the IPv4 device route, so we would ignore RTPROT_KERNEL
routes and not delete them.
We want to track them for various reasons:
- for consistency, there is nothing special except that they might be
added by kernel.
- we expose the routes of NMIP4Config/NMIP6Config on D-Bus. That should
include also routes such as device routes. Note, this commit changes
that we now expose device routes on D-Bus too.
For IPv6, we create device routes when processing the RA and add it to
NMIP6Config like any other route. For IPv4 we didn't do that. Instead
we created the list of device routes during nm_ip4_config_commit() and
passed it to nm_platform_ip_route_sync().
When merging IP addresses, we keep the best addr_source and the internally
configured timestamps. Since the check for the timestamp considers addr_source,
we must move the check before merging addr_source.
For kernel, route ID compare identical according to NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID.
Well, mostly. In practice, NM ignores several route properties that
kernel considers part of the ID too. This leaves the possibility that
kernel allows addition of two routes that compare idential for
NetworkManager.
Anyway, NMIP4Config/NMIP6Config should use the same equality as platform
cache. Otherwise, there is the odd situation that ip-config merges routes
that are treated as different by kernel.
For IP addresses the ID operator already corresponded to what kernel
does. There is no change for addresses.
Note that NMSettingIPConfig also uses a different algorithm for
comparing routes. But that doesn't really matter here, it it differed
before too.
In many cases we want to treat IPv4 and IPv6 generically. That looks nicer
if we distingish by an @addr_family integer, instead of a boolean.
Replace the @is_ipv6 boolean with an @addr_family paramter. The @is_ipv6
boolean is inconsistent with other places where we use @is_ipv4 to
indicate the opposite. Eventually, we should use @addr_family
everywhere.
Also, at the call site it's not immediately clear what TRUE/FALSE means,
here AF_INET/AF_INET6 is better.
- cleanup data type and use guint32 consistently. We might want to
introduce a new "infinity" value. But since libnm's
NM_SETTING_IP_CONFIG_DHCP_TIMEOUT asserts against the range
0 - G_MAXINT32, we cannot express it as -1 anyway. So, infinity
will have the numerical value G_MAXINT32, hence guint32 is just
fine.
- make use of existing ipv6.dhcp-timeout setting and add global
default configuration in NetworkManager.conf
- instead of having subclasses call nm_device_set_dhcp_timeout(),
add a virtual function get_dhcp_timeout().
A typo in the new dhcp-timeout option caused the dhclient daemon to exit
with error when the dhcp-timeout option was specified.
This prevents dhcp connection to be upped.
Fixes: 82ef497cc9
Previously when the interface created by pppd was already the one we
expected, we would rename it to itself and remove the device from the
manager. Don't do it.
Fixes: 6c3195931e
Remove NMDefaultRouteManager. Instead, add the default-route to the
NMIP4Config/NMIP6Config instance.
This basically reverts commit e8824f6a52.
We added NMDefaultRouteManager because we used the corresponding to `ip
route replace` when configuring routes. That would replace default-routes
on other interfaces so we needed a central manager to coordinate routes.
Now, we use the corresponding of `ip route append` to configure routes,
and each interface can configure routes indepdentently.
In NMDevice, when creating the default-route, ignore @auto_method for
external devices. We shall not touch these devices.
Especially the code in NMPolicy regarding selection of the best-device
seems wrong. It probably needs further adjustments in the future.
Especially get_best_ip_config() should be replaced, because this
distinction VPN vs. devices seems wrong to me.
Thereby, remove the @ignore_never_default argument. It was added by
commit bb75026004, I don't think it's
needed anymore.
This brings another change. Now that we track default-routes in
NMIP4Config/NMIP6Config, they are also exposed on D-Bus like regular
routes. I think that makes sense, but it is a change in behavior, as
previously such routes were not exposed there.
Default-routes are for the most part like regular routes. Add support to
track them like regular routes in NMIP4Config/NMIP6Config.
One thing is, sometimes we need to figure out whether an ip-config
instance has a default-route. For that, keep track of the best
default-route (there might be multiple) and expose it. That is
the most complicated part of this patch, because there are so many
places where the list of routes gets modified (replace, intersect,
subtract, merge, add), and they all need to take care of updating
the best default-route.
In a next patch, NMDefaultRouteManager will be dropped and default-routes
will be tracked by NMIP4Config/NMIP6Config.