The rules were added to the list using g_slist_append() and then
applied one at time using "iptables --insert" which puts them at the
beginning of the chain, reversing the initial order.
Instead, list them in the desired order and use g_slist_prepend() to
achieve the same result. This has no functional changes.
The function can now be called on unrealized devices before the
initial unmanaged flags are set and for those devices
nm_device_get_managed() will return TRUE. Since we only accept
states > UNMANAGED, return early when the condition is not met.
Fixes the following failed assertion:
carrier_changed: assertion 'priv->state >= NM_DEVICE_STATE_UNAVAILABLE' failed
https://bugzilla.gnome.org/show_bug.cgi?id=760844
The availability checks are called from places that don't assume the device
will be removed mid-air. Call the removal routine only when we're the very
last thing that's being done.
During nm_device_unrealize(), the connection might still
have some connections that only get removed later. We must
garbage collect unrealized devices when they loose their
available-connections, not during unrealize.
Fixes: 436ec5b8e3
Apply MTU and hop limit when managed or other flag is set as well. This wasn't
the case for the first RA and the previous commit made it slightly worse by
always ignoring it.
Fixes: ad2584c375
With DHCPv6 it might be quite some time (we may even time out) until we get all
the information to finish activation, but we already have the addresses and
routes.
With the final removal the reason of NOW_UNMANAGED causes the cleanup on the
device to be run, which downs the device:
#0 nm_platform_link_set_down (self=0x555555a29bb0, ifindex=1711) at platform/nm-platform.c:1111
#1 0x00005555555d6ccf in nm_device_take_down (self=self@entry=0x555555c07c70, block=block@entry=1) at devices/nm-device.c:8175
#2 0x00005555555df0c7 in _set_state_full (self=0x555555c07c70, state=NM_DEVICE_STATE_UNMANAGED, reason=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, quitting=quitting@entry=0) at devices/nm-device.c:9825
#3 0x00005555555dfa97 in nm_device_state_changed (self=<optimized out>, state=<optimized out>, reason=<optimized out>) at devices/nm-device.c:10084
#4 0x00005555555e472c in nm_device_set_unmanaged_flags (self=<optimized out>, flag=flag@entry=NM_UNMANAGED_INTERNAL, unmanaged=unmanaged@entry=1, reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED)
at devices/nm-device.c:8745
#5 0x00005555555e54a9 in nm_device_set_unmanaged_quitting (self=<optimized out>) at devices/nm-device.c:8806
#6 0x000055555565b1aa in remove_device (manager=manager@entry=0x555555a4a2c0, device=0x555555c07c70, quitting=quitting@entry=1, allow_unmanage=allow_unmanage@entry=1) at nm-manager.c:833
#7 0x0000555555660b81 in nm_manager_stop (self=0x555555a4a2c0) at nm-manager.c:4389
#8 0x00005555555b3f9b in main (argc=1, argv=0x7fffffffdba8) at main.c:493
The function returns early when autoconnect is off, so there's no reason to
branch for that case below. The signal is only generated for autoconnect=true.
The idea of NMDevice:realize() was to
(1) update the device properties
(2) fail realization if some critical properties are missing
(1) is already done during nm_device_setup_start().
(2) was only implemented by NMDeviceVlan:realize(), but it
basically was just checking whether such a platform device exists.
Other implementations don't do that either and it opens up for a race
when the device gets deleted externally.
All implementations of NMDevice:setup_start() in derived classes
invoke the parent implementation first. Enforce that by moving
NMDevice:setup_start() to realize_start_setup() and only notify
derived classes afterwards via NMDevice:realize_start_notify().
Reapplying a connection should not be done by iterating over and
(unsorted) @diffs array. Instead the order matters! E.g. first layer 2
before IP settings. Thus extracting those individual updates on a per-setting
base to different reapply_*() functions is more complicated, albeit incorrect
in complex cases. We need full control over how to reapply changes, one
after the other.
Also, once we start applying changes, we cannot really abort on error.
We can only continue best-effort and hope for the best.
Also, always reapply certain settings, even if the configuration doesn't
change. That means, if the user externally deletes a static IP address,
he can call reapply() to restore it. Even though he doesn't provide a
different setting to apply.
Also revert the changes to nm_device_reapply_settings_immediately().
Effectively there is little code that can be reused.
Add audit logging.
In certain situations, ethernet links first appear with a zero MAC
address and then the MAC changes some time later. Currently NM does
not deal correctly with this scenario since it initializes wrong
@initial_hwaddr and @permanent_hwaddr on the device and tries to
immediately activate it.
To fix this, initialize the device's addresses only when the MAC
becomes valid and make the device available only at that point.
Instead of using a signal for triggering the generation of a default
connection when the device becomes managed, let the manager wait for a
transition to UNAVAILABLE or DISCONNECTED states.
This partially reverts b3b0b46250 ("device: retry creation of
default connection after link is initialized").
We inconsistently use gulong,guint,int types to store signal handler
id, but the type returned by g_signal_connect() is a gulong.
This has no practical consequences because a int/guint is enough to
store the value, however it is better to use a consistent type, also
because nm_clear_g_signal_handler() accepts a pointer to the signal id
and thus it must be always called with the same pointer type.
If @ip_ifindex is zero, the IP interface has disappeared and
there's no point in updating @ip_iface.
Actually, unconditionally updating @ip_iface is dangerous because it
breaks the assumption used by other functions (as
nm_device_get_ip_ifindex()) that a non-NULL @ip_iface implies a valid
@ip_ifindex. This was causing the scary failure:
devices/nm-device.c:666:get_ip_iface_identifier: assertion failed: (ifindex)
https://bugzilla.redhat.com/show_bug.cgi?id=1268617
Otherwise the lacking IS_SOFTWARE capability may cuase the connections not to
be available on software devices and the devices would get garbage-collected at
the end of unrealize().
The nm_device_master_add_slave() also modifies slave's master property which
impacts the ability to enslave. When called in reaction to external
master property change we now no longer call enslave_slave which used to queue
the recheck previously:
# nmcli c add type bridge ifname br0
# ip link add dummy0 type dummy
# ip link set dummy0 up
# ip link set dummy0 master br0 # We should recheck for assumed connection
# here, since dummy0 can now be assumed.
We only need to do that when we're replacing the master with a different
one. Just after the link creation is has no master and we'd remove it
from the master device here.
Fixes autoconnect after the device is realized again:
# nmcli c add type team
# nmcli c up team
# nmcli d dis nm-team # autoconnect is blocked
# nmcli c del team # the is unrealized
# nmcli c add type team # the device is realized again, not
# activating with the new connection
After the device is unrealized a lot of its properites are reset. Notably, it
doesn't have an ifindex anymore so there's nothing to unconfigure really. This
makes at least NMDeviceBond unhappy:
(bond device with a slave is removed externally)
NetworkManager[21022]: <info> (bond0): device state change: activated -> unmanaged (reason 'unmanaged') [100 10 3]
NetworkManager[21022]: nm_platform_link_release: assertion 'master > 0' failed
Program received signal SIGTRAP, Trace/breakpoint trap.
g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
1046 g_private_set (&g_log_depth, GUINT_TO_POINTER (depth));
(gdb) bt
#0 0x00007ffff4ec88c3 in g_logv (log_domain=0x5555557592b1 "NetworkManager", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=args@entry=0x7fffffffd370) at gmessages.c:1046
#1 0x00007ffff4ec8a3f in g_log (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7ffff4f3673d "%s: assertion '%s' failed")
at gmessages.c:1079
#2 0x00007ffff4ec8a79 in g_return_if_fail_warning (log_domain=log_domain@entry=0x5555557592b1 "NetworkManager", pretty_function=pretty_function@entry=0x55555575ea50 <__FUNCTION__.33801> "nm_platform_link_relea8
#3 0x000055555560559a in nm_platform_link_release (self=0x555555a27bb0 [NMLinuxPlatform], master=master@entry=0, slave=slave@entry=3) at platform/nm-platform.c:1326
#4 0x00005555555b506e in release_slave (device=<optimized out>, slave=0x555555b6d770 [NMDeviceEthernet], configure=<optimized out>) at devices/nm-device-bond.c:423
#5 0x00005555555dab7b in nm_device_master_release_one_slave (self=self@entry=0x555555bf0cc0 [NMDeviceBond], slave=0x555555b6d770 [NMDeviceEthernet], configure=configure@entry=1, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED) at devices/nm-device.c:1137
#6 0x00005555555dadb6 in nm_device_master_release_slaves (self=self@entry=0x555555bf0cc0 [NMDeviceBond]) at devices/nm-device.c:2344
#7 0x00005555555dd12f in nm_device_cleanup (self=self@entry=0x555555bf0cc0 [NMDeviceBond], reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED, cleanup_type=cleanup_type@entry=CLEANUP_TYPE_DECONFIGURE)
at devices/nm-device.c:9133
#8 0x00005555555de3ea in _set_state_full (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=
NM_DEVICE_STATE_REASON_NOW_UNMANAGED, quitting=quitting@entry=0) at devices/nm-device.c:9510
#9 0x00005555555dedb7 in nm_device_state_changed (self=self@entry=0x555555bf0cc0 [NMDeviceBond], state=state@entry=NM_DEVICE_STATE_UNMANAGED, reason=reason@entry=NM_DEVICE_STATE_REASON_NOW_UNMANAGED)
at devices/nm-device.c:9769
#10 0x00005555555e11b4 in nm_device_unrealize (self=self@entry=0x555555bf0cc0 [NMDeviceBond], remove_resources=remove_resources@entry=0, error=error@entry=0x7fffffffd788) at devices/nm-device.c:2062
#11 0x000055555565c9c5 in _platform_link_cb_idle (data=0x555555c6e2b0) at nm-manager.c:2055
#12 0x00007ffff4ec179a in g_main_context_dispatch (context=0x555555a226c0) at gmain.c:3109
#13 0x00007ffff4ec179a in g_main_context_dispatch (context=context@entry=0x555555a226c0) at gmain.c:3708
#14 0x00007ffff4ec1ae8 in g_main_context_iterate (context=0x555555a226c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3779
#15 0x00007ffff4ec1dba in g_main_loop_run (loop=0x555555a22780) at gmain.c:3973
#16 0x00005555555b3e5f in main (argc=1, argv=0x7fffffffdb18) at main.c:488
An IPv6 address might have been added externally and the device is yet to
traverse to a connected state.
On the other hand, the externally added devices still traverse through
DISCONNECTED state and we don't want to attempt the LL addition there. Let's
check if the link still exists instead.