No need for the setter/getter of this property.
Immutable properties are so much nicer. Remove the setter and
ensure that the nm_plugin_missing property is only set during
object construction.
Unify the two check_ip_done() and check_ip_failed() functions into a
single one to have all the state transition logic in the same place.
This also fixes a regression introduced by commit 553717bb1c
("device: don't set ip4_state=IP_FAIL for ipv4.method=disabled").
After that commit the device immediately proceeded to IP_CHECK when
there was a disabled/ignore method. Now we wait for the termination of
the other method, like it used to be.
Fixes: 553717bb1chttps://bugzilla.gnome.org/show_bug.cgi?id=771579
Some drivers (brcmfmac) don't change the MAC address right away.
NetworkManager works around that by waiting synchronously until
the address changes (commit 1a85103765).
wpa_supplicant on the other hand, only re-reads the MAC address
when changing state from DISABLED to ENABLED, which happens when
the interface comes up.
That is a bug in wpa_supplicant and the driver, but we can work-around by
waiting until the MAC address actually changed before setting the interface
IFF_UP. Also note, that there is still a race in wpa_supplicant which might
miss a change to DISABLED state altogether.
https://bugzilla.gnome.org/show_bug.cgi?id=770504https://bugzilla.redhat.com/show_bug.cgi?id=1374023
Instead of letting the sub-class check the "enabled" state, let
it be handled by nm_device_bring_up().
Note that nm_device_get_enabled() only has two implementations:
NMDeviceModem:bring_up() and NMDeviceWifi:bring_up().
Long ago before commit 1b49f94, NetworkManager did not touch the
MAC address at all. Since 0.8.2 NetworkManager would modify the
MAC address, and eventually it would reset the permanent MAC address
of the device.
This prevents a user from externally setting the MAC address via tools
like macchanger and rely on NetworkManager not to reset it to the
permanent MAC address. This is considered a security regression in
bgo#708820.
This only changed with commit 9a354cd and 1.4.0. Since then it is possible
to configure "cloned-mac-address=preserve", which instead uses the "initial"
MAC address when the device activates.
That also changed that the "initial" MAC address is the address which was
externally configured on the device as last. In other words, the
"initial" MAC address is picked up from external changes, unless it
was NetworkManager itself who configured the address when activating a
connection.
However, in absence of an explicit configuration the default for
"cloned-mac-address" is still "permanent". Meaning, the user has to
explicitly configure that NetworkManager should not touch the MAC address.
It makes sense to change the upstream default to "preserve". Although this
is a change in behavior since 0.8.2, it seems a better default.
This change has the drastic effect that all the existing connections
out there with "cloned-mac-address=$(nil)" change behavior after upgrade.
I think most users won't notice, because their devices have the permanent
address set by default anyway. I would think that there are few users
who intentionally configured "cloned-mac-address=" to have NetworkManager
restore the permanent address.
https://bugzilla.gnome.org/show_bug.cgi?id=770611
... and don't set ip6_state=IP_FAIL for ipv6.method=ignore.
The disabled state is like having an empty NMIP4Config object.
It should not result in %IP_FAIL state. Instead, we just want
to proceed and commit an empty NMIP4Config instance.
This was introduced by commit 0652d9c596,
which I think was wrong.
Likewise, for ipv6.method=ignore we also don't want to mark the
IP state as failed. Instead, we want to proceed and set IP_DONE
right away -- without commiting anything, which is a difference
to the IPv4 case.
This is especially important, because an ip4_state/ip6_state of IP_FAIL
causes nm_device_can_assume_active_connection() to return FALSE, which
means we unmanage devices at shutdown. Ony might say that it doesn't
matter so much for a device without IP configuration, but imagine a
bond with VLANs on top that only has Layer 2 configuration. This will
bring down the entire stack.
With this change, devices with IP methods disabled/ignore stay up on
exit of NetworkManager (rh#1371126). Of course, that means on restart
software devices stay unamanged due to external-down (because since
commit e1edcda, devices without IP address are also external-down).
So, this really just fixes one scenario, breaking another one.
This should be fixed with bgo#746440 by not assuming connections.
https://bugzilla.redhat.com/show_bug.cgi?id=1371126
brcmfmac and possibly other drivers don't change the MAC address
right away, but instead the result is delayed. That is problematic
because we cannot continue activation before the MAC address is
settled.
Add a hack to workaround the issue by waiting until the MAC address
changed.
The previous attempt to workaround this was less intrusive: we would
just refresh the link once and check the result. But that turns out
not to be sufficent for all cases. Now, wait and poll.
https://bugzilla.gnome.org/show_bug.cgi?id=770456https://bugzilla.redhat.com/show_bug.cgi?id=1374023
After the fix in [1], if the connection is assumed we don't update its
firewall zone. The goal of that change was to prevent NM from
interfering with the configuration done externally on devices not
created by NM.
However if there is an assumed persistent connection active on the
device NM touches the configuration in other ways, for example it
configures DHCP and manages the default route. So it seems correct to
also update the firewall zone.
OTOH, if the connection is assumed-generated there is no persistent
connection specifying a firewall zone and updating it makes no sense.
Bug [1] was about not interfering with devices unknown to NM (for
which there is no persistent connection) and so this change should not
conflict with the previous fix.
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1098281https://bugzilla.redhat.com/show_bug.cgi?id=1366288
At this point we don't know if the slave has been using an assumed
connection that just vanished -- the best bet is to let the device be.
If it's meant to be unenslaved, it won't be due to an external event.
https://bugzilla.redhat.com/show_bug.cgi?id=1357738
When a software device unrealizes, we want to forget about the "user-explict"
unmanaged state. It means, that after a software device is deleted, the
"user-explict" managed flag will be cleared for that device.
It might be nice to preserve the managed-state after deletion of the device.
However, the unrealized-device only exists as long as we have a connection
for the device. That means, before this patch whether the unmanaged flag
was forgotten depends on whether the user had some connections that keep
the device alive as unrealized. That behavior was complicated, just don't
do that.
It seems some drivers return success for nm_platform_link_set_address(),
but at that point the address did not yet actually change *sigh*.
It changes a bit later, possibly after setting the device up.
Add a workaround to retry reading the MAC address when platform indicates
success but the address still differs at first.
https://bugzilla.gnome.org/show_bug.cgi?id=770456
When activating a connection, it may fail with nmcli reporting:
$ nmcli connection up id "Wired Connection 1"
Error: Connection activation failed: Active connection removed before it was initialized
This should be easily reproducible by having a connection "Wired Connection 1" with
cloned-mac-address set to random. When the connection is already active on a device,
re-activating with
$ nmcli connection up id "Wired Connection 1"
fails.
We first create a queued-activation and tear down the existing
connection:
device (enp0s25): state change: deactivating -> disconnected (reason 'new-activation')
Shortly after we see:
device[0x557d02cdb0c0] (enp0s25): set-hw-addr: setting MAC address to 'AA:BB:CC:DD:EE:FF' (reset, deactivate)...
device[0x557d02cdb0c0] (enp0s25): taking down device
later, we get:
device (enp0s25): link disconnected
device[0x557d02cdb0c0] (enp0s25): queued state change to unavailable due to carrier-changed (id 17290)
in the meantime, the queued activation request starts:
device (enp0s25): Activation: starting connection 'my-wired' (ca058ec5-8a47-4e1e-b38e-962b71c4699e)
but the device already transitions to unavailable
device[0x557d02cdb0c0] (enp0s25): running queued state change to unavailable (id 17290)
device (enp0s25): state change: disconnected -> unavailable (reason 'carrier-changed') [30 20 40]
which kills the new activation request:
active-connection[0x557d02c10e40]: set state deactivated (was unknown)
Just delay a carrier-lost handling if we have any queued activation
requests.
(cherry picked from commit d4e9b30320)
When a assumed software device is brought down externally, it becomes
UNMANAGED_EXTERNAL_DOWN and its state goes from ACTIVATED directly to
UNMANAGED. In such case, we shouldn't flush the IP configuration
(addresses and routes) present on the device.
To fix this, clean up the device with CLEANUP_TYPE_KEEP and modify
nm_device_cleanup() not to flush addresses and devices with such flag.
https://bugzilla.redhat.com/show_bug.cgi?id=1363995
(cherry picked from commit 45cd3302dc)
Instead of updating the device-statistic counters only periodically as
we refresh the link, update them on every link-changed event from
platform.
That means, also for devices that have RefreshRateMs at zero, the values
will be updated at random times when the link information changes.
The difference is, that previously the counters would be zero unless
RefreshRateMs was set. Now, they have some (probably stale) values
which however are not guaranteed to be kept up-to-date.
Also, now we refresh more often then promised by RefreshRateMs. But the API
technically doesn't specify that, so if we find there is a problem with
this, we may revert it later.
Originally, "nm-device-statistics.c" contained code to fetch the device
counters via netlink. As now the netlink part is handled by NMPlatform,
the code can be simplified by merging it back to NMDevice.
Add statistics interface to all device instances. When active, the
properties of this interface are refreshed whenever there is network
activity for the device.
Activation is performed by changing RefreshRateMs property. If set to
zero, the interface is deactivated. If set to other value, the rest of
the interface properties are refreshed whenever the related network
metric changes, being RefreshRateMs the minimum time between property
changes, in milliseconds.
Commit f85941ee91 ("device: don't try to generate ipv6ll address for
disconnected devices") disabled the generation of IPv6 link-local
addresses for disconnected devices to fix a crash. However that broke
the following:
$ ip a f dev eth0
$ systemctl start NetworkManager
$ nmcli d
DEVICE TYPE STATE CONNECTION
eth0 ethernet disconnected eth0
$ ip a a dev eth0 2001::42/64
$ ip a show eth0
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 52:52:00:61:32:81 brd ff:ff:ff:ff:ff:ff
inet6 2001::42/64 scope global
valid_lft forever preferred_lft forever
(no link-local address)
Instead, enable the generation of a link-local address even if the
device is disconnected and fix nm_device_get_ip_iface_identifier() to
not require a connection if @ignore_token is set.
Fixes: f85941ee91
When the master connection deactivates, we also fail slave
connections; but if the master deactivation happens just before a
slave reaches the PREPARE state, we failed to notice it and keep
the slave stuck without chance of progressing. Fix this.
Since nm_device_slave_notify_release() is called from outside the
activation chain of the slave device (it gets called from the master
device) there might be pending activation sources scheduled, clear
them before queueing a state change.
If the device is disconnected because it can't be assumed due to lack
of IP configuration, don't try to generate an ipv6 link-local address,
as this requires a connection.
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 __GI_abort () at abort.c:89
#2 g_assertion_message (domain=domain@entry=0x5f41b4 "NetworkManager", file=file@entry=0x5ef9b5 "devices/nm-device.c", line=line@entry=831,
func=func@entry=0x5f3220 <__FUNCTION__.37383> "nm_device_get_ip_iface_identifier", message=message@entry=0x1e86100 "assertion failed: (connection)") at gtestutils.c:2429
#3 g_assertion_message_expr (domain=domain@entry=0x5f41b4 "NetworkManager", file=file@entry=0x5ef9b5 "devices/nm-device.c", line=line@entry=831,
func=func@entry=0x5f3220 <__FUNCTION__.37383> "nm_device_get_ip_iface_identifier", expr=expr@entry=0x5e65c6 "connection") at gtestutils.c:2452
#4 nm_device_get_ip_iface_identifier (self=self@entry=0x1e612a0, iid=iid@entry=0x7fffce40e3d0, ignore_token=ignore_token@entry=1) at devices/nm-device.c:831
#5 check_and_add_ipv6ll_addr (self=self@entry=0x1e612a0) at devices/nm-device.c:5983
#6 queued_ip6_config_change (user_data=0x1e612a0) at devices/nm-device.c:9489
#7 g_main_dispatch (context=0x1d3e060) at gmain.c:3154
#8 g_main_context_dispatch (context=context@entry=0x1d3e060) at gmain.c:3769
#9 g_main_context_iterate (context=0x1d3e060, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3840
#10 g_main_loop_run (loop=0x1d3ab00) at gmain.c:4034
#11 main (argc=1, argv=0x7fffce40e6a8) at main.c:411
https://bugzilla.redhat.com/show_bug.cgi?id=1351633
<info> [1467793329.6313] device (veth-guest): Activation: starting connection 'my-wired' (ca058ec5-8a47-4e1e-b38e-962b71c4699e)
<debug> [1467793329.6313] device[0x55af2884bf90] (veth-guest): activation-stage: schedule activate_stage1_device_prepare,2 (id 510)
<warn> [1467793329.6314] device (veth-guest): disconnecting connection 'my-wired' for new activation request.
<info> [1467793329.6315] device (veth-guest): state change: disconnected -> deactivating (reason 'new-activation') [30 110 60
A warning is too verbose. This is not an unusual condition, it's just that
a new activation supersedes an other one.
Trying to set a property on a device that does not exist is not something
necessarily wrong. Don't print error/warning messages.
<trace> [1467707267.2887] device[0x55a74adbdaf0] (enp0s25): set-hw-addr: setting MAC address to 'AA:BB:CC:DD:EE:FF' (reset, unmanage)...
<debug> [1467707267.2887] platform: link: setting '(null)' (2) hardware address
<debug> [1467707267.2887] platform-linux: link: change 2: address: 68:F7:28:61:68:F7 (6 bytes)
<debug> [1467707267.2887] platform-linux: do-request-link: 2
<debug> [1467707267.2888] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 226
<debug> [1467707267.2888] platform-linux: netlink: recvmsg: error message from kernel: No such device (19) for request 227
<error> [1467707267.2888] platform-linux: do-change-link[2]: failure changing link: failure 19 (No such device)
<warn> [1467707267.2888] device (enp0s25): set-hw-addr: failed to reset MAC address to 68:F7:28:61:68:F7 (unmanage)
During shutdown, we unmanage Wi-Fi devices, and during NMDevice:deactivate()
we would reset to initial MAC address.
However, NMDeviceWifi:deactivate() would reset it again to the scanning one.
Fix that to properly restore the initial MAC address on the device
when NetworkManager exits.
Fixes: 4b2e375b33
Wi-Fi device first have a state-transition "disconnected -> prepare"
on which they run activate_stage1_device_prepare() and set the MAC
address the first time.
Later, after getting secrets, they have a state transition "need-auth ->
prepare" and end up calling nm_device_hw_addr_set_cloned() again. In this
case, we must not regenerate a new MAC address but bail out.
There is a small uncertainty there, because we are not sure that the previously
generated connection really entailed the same settings. But since we always
call nm_device_hw_addr_reset() during device deactivation, this cannot be
a left-over from a previous activation and is thus the same activation
request.
Instead of letting different subclasses call reset in their
virtual deactivate() function, do it in the parent class.
This works nicely, because the parent know whether the MAC
address is currently modified.
For the per-connection settings "ethernet.cloned-mac-address"
and "wifi.cloned-mac-address", and for the per-device setting
"wifi.scan-rand-mac-address", we may generate MAC addresses using
either the "random" or "stable" algorithm.
Add new properties "generate-mac-address-mask" that allow to configure
which bits of the MAC address will be scrambled.
By default, the "random" and "stable" algorithms scamble all bits
of the MAC address, including the OUI part and generate a locally-
administered, unicast address.
By specifying a MAC address mask, we can now configure to perserve
parts of the current MAC address of the device. For example, setting
"FF:FF:FF:00:00:00" will preserve the first 3 octects of the current
MAC address.
One can also explicitly specify a MAC address to use instead of the
current MAC address. For example, "FF:FF:FF:00:00:00 68:F7:28:00:00:00"
sets the OUI part of the MAC address to "68:F7:28" while scrambling
the last 3 octects.
Similarly, "02:00:00:00:00:00 00:00:00:00:00:00" will scamble
all bits of the MAC address, except clearing the second-least
significant bit. Thus, creating a burned-in address, globally
administered.
One can also supply a list of MAC addresses like
"FF:FF:FF:00:00:00 68:F7:28:00:00:00 00:0C:29:00:00:00 ..." in which
case a MAC address is choosen randomly.
To fully scamble the MAC address one can configure
"02:00:00:00:00:00 00:00:00:00:00:00 02:00:00:00:00:00".
which also randomly creates either a locally or globally administered
address.
With this, the following macchanger options can be implemented:
`macchanger --random`
This is the default if no mask is configured.
-> ""
while is the same as:
-> "00:00:00:00:00:00"
-> "02:00:00:00:00:00 02:00:00:00:00:00"
`macchanger --random --bia`
-> "02:00:00:00:00:00 00:00:00:00:00:00"
`macchanger --ending`
This option cannot be fully implemented, because macchanger
uses the current MAC address but also implies --bia.
-> "FF:FF:FF:00:00:00"
This would yields the same result only if the current MAC address
is already a burned-in address too. Otherwise, it has not the same
effect as --ending.
-> "FF:FF:FF:00:00:00 <MAC_ADDR>"
Alternatively, instead of using the current MAC address,
spell the OUI part out. But again, that is not really the
same as macchanger does because you explictly have to name
the OUI part to use.
`machanger --another`
`machanger --another_any`
-> "FF:FF:FF:00:00:00 <MAC_ADDR> <MAC_ADDR> ..."
"$(printf "FF:FF:FF:00:00:00 %s\n" "$(sed -n 's/^\([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) \([0-9a-fA-F][0-9a-fA-F]\) .*/\1:\2:\3:00:00:00/p' /usr/share/macchanger/wireless.list | xargs)")"