Ethernet, WiFi, and VLAN used the same implementation for initial address.
Ethernet and WiFi used the same implementation (and duplicated code) for
permanent MAC address, plus they both used ethtool in what should be
generic code, which is better done in the platform.
Always intern string from udev_get_driver().
We use the result of udev_get_driver() for setting NMPlatformLink.driver.
In all other cases, we already set that value to an interned string,
which simplifies memory handling.
As it was, the lifetime of that string was tied to the lifetime of the
GUdevDevice.
This is not a stelar solution, but we assume that the overall numbers
of different drivers is limited so we don't leak large amounts of
memory.
link_extract_type() would return the NMLinkType and a
@type_name string. If the type was unknown, this string
was rtnl_link_get_type() (IFLA_INFO_KIND).
Split up this behavior and treat those values independently.
link_extract_type() now only detects the NMLinkType. Most users
don't care about unknown types and can just use nm_link_type_to_string()
to get a string represenation.
Only nm_platform_link_get_type_name() (and NMDeviceGeneric:type_description)
cared about a more descriptive type. For that, modify link_get_type_name()
to return nm_link_type_to_string() if NMLinkType could be detected.
As fallback, return rtnl_link_get_type().
Also, rename the field NMPlatformLink:link_type to "kind". For now this
field is mostly unused. It will be used later when refactoring platform
caching.
Instead of having a nm_platform_free() function, use NM_DEFINE_SINGLETON_WEAK_REF()
and register a weak reference. That way, users who want to free the platform
instance can just unref it.
We already have nm_*_platform_setup() that gets specified
via -DSETUP. This SETUP() hook gives us all the flexiblity
we need to customize our singleton, so just do any required
setup there.
Also, it would be easier to add an alternative (hypotetical)
nm_fake_platform_setup_custom() to customize the singleton then to
parametrize the NMPlatform:setup() implementation. So this virtual
function is less flexible and redundant.
We have two hooks to modify setup of the platform singleton:
nm_linux_platform_setup() and the virtual setup() function.
On the other hand, nm_platform_setup() limits us by accepting
only a GType, instead of a prepeared platform instance.
Make the nm_platform_setup() method more flexible, so that we can
later drop the setup() hook.
setup() can be used to initialize a NMPlatform instance that is
registered as singleton via nm_platform_setup(). It should not
be used to initialize the object.
Prior to c6529a9d74, this change was
not possible because constructed() will call back into nm_platform_*()
functions, without having the singleton instance setup.
Most nm_platform_*() functions operate on the platform
singleton nm_platform_get(). That made sense because the
NMPlatform instance was mainly to hook fake platform for
testing.
While the implicit argument saved some typing, I think explicit is
better. Especially, because NMPlatform could become a more usable
object then just a hook for testing.
With this change, NMPlatform instances can be used individually, not
only as a singleton instance.
Before this change, the constructor of NMLinuxPlatform could not
call any nm_platform_*() functions because the singleton was not
yet initialized. We could only instantiate an incomplete instance,
register it via nm_platform_setup(), and then complete initialization
via singleton->setup().
With this change, we can create and fully initialize NMPlatform instances
before/without setting them up them as singleton.
Also, currently there is no clear distinction between functions
that operate on the NMPlatform instance, and functions that can
be used stand-alone (e.g. nm_platform_ip4_address_to_string()).
The latter can not be mocked for testing. With this change, the
distinction becomes obvious. That is also useful because it becomes
clearer which functions make use of the platform cache and which not.
Inside nm-linux-platform.c, continue the pattern that the
self instance is named @platform. That makes sense because
its type is NMPlatform, and not NMLinuxPlatform what we
would expect from a paramter named @self.
This is a major diff that causes some pain when rebasing. Try
to rebase to the parent commit of this commit as a first step.
Then rebase on top of this commit using merge-strategy "ours".
Some out of tree drivers add Ethernet devices that are supposed to be managed
by other their tooling, e.g. VirtualBox or VMWare.
Rather than hardcoding their drivers (at least VirtualBox doesn't even set a
"driver" property in sysfs) or hardcoding a logic that identifies such devices
let's just add a possibility to blacklist them in udev. This makes it possible
for whoever who ships such a driver to ship rules that prevent NetworkManager
from managing the device itself.
Furthermore it makes it possible for the user with special needs leverage the
flexibility of udev rules to override the defaults. In the end the user can
decide to let NetworkManager manage default-unmanaged interfaces such as VEth
or turn on default-unmanaged for devices on a particular bus.
An udev rule for VirtualBox would look like this:
SUBSYSTEM=="net", ENV{INTERFACE}=="vboxnet[0-9]*", ENV{NM_UNMANAGED}="1"
Create a NMRouteManager singleton.
Refactor, no functional changes apart from change of log domain from
LOGD_PLATFORM to LOGD_CORE.
Subsequent commit will keep track of the conflicting routes, avoid overwriting
older ones with newer ones and apply the new ones when the old ones go away.
Since f32075d2fc, we remove the kernel
added IPv4 device route, and re-add it with appropriate metric.
This could potentially replace existing, conflicting routes. Be more
careful and only take any action when we don't have a conflicting
route and when we add the address for the first time.
The motivation for this was libreswan which might install a VPN route
for a subnet that we also have configured on an interface. But the route
conflict could happen easily for other reasons, for example if you
configure a conflicting route manually.
Don't replace the device route if we have any indication that
a conflict could arise.
https://bugzilla.gnome.org/show_bug.cgi?id=723178
For IPv4 addresses, the kernel automatically adds a route when
configuring an IP address. Unfortunately, there is no way to control
this behavior or to set the route metric.
Fix this, by adding our own route and removing the kernel provided
one.
Note that this adds a major change in that we no longer call
nm_ip4_config_commit() for assumed devices.
https://bugzilla.gnome.org/show_bug.cgi?id=723178
Signed-off-by: Thomas Haller <thaller@redhat.com>
config.h should be included from every .c file, and it should be
included before any other include. Fix that.
(As a side effect of how I did this, this also changes us to
consistently use "config.h" rather than <config.h>. To the extent that
it matters [which is not much], quotes are more correct anyway, since
we're talking about a file in our own build tree, not a system
include.)
These lines are part of NM for a very long time.
I think they are wrong, because the default route is not
added to the NMIP4Config/NMIP6Config objects.
Signed-off-by: Thomas Haller <thaller@redhat.com>
Add a new enum NMPlatformGetRouteMode. This extends the existing
functions nm_platform_ip4_route_get_all() and nm_platform_ip6_route_get_all()
to return default routes only.
Signed-off-by: Thomas Haller <thaller@redhat.com>
Kernel, netlink an NMPlatformRoute treat route metrics as
uint32. Fix several places to use the exact type.
Signed-off-by: Thomas Haller <thaller@redhat.com>
They are defined as gint32 but are assigned a guint32 value and
then immediately passed back to the caller of _address_get_lifetime()
as guint32. They can never be negative, and may receive values
greater than G_MAXINT32, so they should be unsigned.
NMIP4Configs and NMIP6Configs are never supposed to contain a default
route, and thus nm_platform_ip6_route_sync() should never have to deal
with one. Unfortunately, if it *does* get passed a default route, it
will add it even if it was already there. This will result in an
RTM_NEWROUTE notification, which will cause NMPlatform to emit
ip6-route-changed, which will result in NMDevice doing some work and
then calling nm_ip6_config_commit(), which will result in NMIP6Config
passing the same list of routes to nm_platform_ip6_route_sync() again,
including the default route, which will cause NMPlatform to add the
route again...
(Something eventually causes this cycle to get broken, but it starts
up again the next time NM receives an RA.)
Fix this by having the route_sync() functions never add/modify the
default route (They were already not deleting it.)
Deleting an IPv4 address using libnl requires the proper peer address.
Pass the address of the peer on to nm_platform_ip4_address_delete().
Signed-off-by: Thomas Haller <thaller@redhat.com>
This patch requires both upstream kernel support for
IFLA_INET6_ADDR_GEN_MODE which was merged in this patch:
ipv6: addrconf: implement address generation modes
bc91b0f07ada5535427373a4e2050877bcc12218
and corresponding libnl support, merged in these patches:
veth: add kernel header linux/veth.h for VETH defines
9dc6e6da90016a33929f262bea0187396e1a061b
link: update copy of kernel header include/linux/if_link.h
b51815a9dbd8e45fd2558bbe337fb360ca2fd861
link/inet6: add link IPv6 address generation mode support
558f966782539f6d975da705fd73cea561c9dc83
Change all DBUS_TYPE_G_UCHAR_ARRAY properties to G_TYPE_BYTES, and
update corresponding APIs. Notably, this means they are now refcounted
rather than being copied.
Update the rest of NM for the changes. The daemon still converts SSIDs
to GByteArrays internally, because changing it to use GBytes has lots
of trickle-down effects. It can possibly be changed later.
Lots of old code used struct ether_addr to store hardware addresses,
and ether_aton() to parse them, but more recent code generally uses
guint8 arrays, and the nm_utils_hwaddr_* methods, to be able to share
code between ETH_ALEN and INFINIBAND_ALEN cases. So update the old
code to match the new. (In many places, this ends up getting rid of
casts between struct ether_addr and guint8* anyway.)
(Also, in some places, variables were switched from struct ether_addr
to guint8[] a while back, but some code still used "&" when referring
to them even though that's unnecessary now. Clean that up.)
Since the API has not changed at this point, this is mostly just a
matter of updating Makefiles, and changing references to the library
name in comments.
NetworkManager cannot link to libnm due to the duplicated type/symbol
names. So it links to libnm-core.la directly, which means that
NetworkManager gets a separate copy of that code from libnm.so.
Everything else links to libnm.
If the timestamp is set to zero, the to_string() functions treat the lifetime
as based on *now*. For nm_platform_ip_address_cmp_expiry() this makes no
sense, because there is no absolute exiry to compare. Instead compare
them as expire earlier then the other address.
Signed-off-by: Thomas Haller <thaller@redhat.com>
The "lifetime" part when printing an address in nm_platform_ip[46]_address_to_string()
is supposed to show the raw, internal values of the address.
We already have the "lft" and "pref" output that presents the expiries based on now.
These fields are already crafted to show what the user probably wants
to see when looking at debugging log. "lifetime" should not do any
special casing and just print the raw values.
Signed-off-by: Thomas Haller <thaller@redhat.com>