summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-09-22 20:32:14 +0200
committerThomas Haller <thaller@redhat.com>2021-04-28 13:51:24 +0200
commitba23f8c629efefbe6a90f4e5041ee705df646214 (patch)
treea2b1a0c1d7bd1bba2d86748afd4d46d2a644381c
parent5d8cfb8f4a82cb41ce0bdafadcafca9d58c26746 (diff)
downloadNetworkManager-th/l3cfg-18.tar.gz
core: use NML3ConfigData (WIP)th/l3cfg-18
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am14
-rw-r--r--WIP.txt15
-rw-r--r--src/core/README.l3cfg.md332
-rw-r--r--src/core/devices/adsl/nm-device-adsl.c52
-rw-r--r--src/core/devices/bluetooth/nm-device-bt.c27
-rw-r--r--src/core/devices/nm-acd-manager.c496
-rw-r--r--src/core/devices/nm-acd-manager.h34
-rw-r--r--src/core/devices/nm-device-ethernet.c39
-rw-r--r--src/core/devices/nm-device-ppp.c69
-rw-r--r--src/core/devices/nm-device-private.h16
-rw-r--r--src/core/devices/nm-device-vlan.c1
-rw-r--r--src/core/devices/nm-device-wireguard.c74
-rw-r--r--src/core/devices/nm-device.c4497
-rw-r--r--src/core/devices/nm-device.h16
-rw-r--r--src/core/devices/ovs/nm-device-ovs-bridge.c8
-rw-r--r--src/core/devices/ovs/nm-device-ovs-interface.c10
-rw-r--r--src/core/devices/ovs/nm-device-ovs-port.c8
-rw-r--r--src/core/devices/tests/meson.build1
-rw-r--r--src/core/devices/tests/test-acd.c259
-rw-r--r--src/core/devices/wifi/nm-device-wifi-p2p.c10
-rw-r--r--src/core/devices/wifi/nm-device-wifi.c10
-rw-r--r--src/core/devices/wwan/nm-device-modem.c101
-rw-r--r--src/core/devices/wwan/nm-modem-broadband.c258
-rw-r--r--src/core/devices/wwan/nm-modem-ofono.c120
-rw-r--r--src/core/devices/wwan/nm-modem.c373
-rw-r--r--src/core/devices/wwan/nm-modem.h40
-rw-r--r--src/core/dhcp/nm-dhcp-client.c210
-rw-r--r--src/core/dhcp/nm-dhcp-client.h17
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.c1
-rw-r--r--src/core/dhcp/nm-dhcp-manager.c96
-rw-r--r--src/core/dhcp/nm-dhcp-manager.h13
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c225
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c250
-rw-r--r--src/core/dhcp/nm-dhcp-utils.c300
-rw-r--r--src/core/dhcp/nm-dhcp-utils.h31
-rw-r--r--src/core/dhcp/tests/test-dhcp-dhclient.c1
-rw-r--r--src/core/dhcp/tests/test-dhcp-utils.c567
-rw-r--r--src/core/dnsmasq/nm-dnsmasq-manager.c51
-rw-r--r--src/core/dnsmasq/nm-dnsmasq-manager.h10
-rw-r--r--src/core/meson.build1
-rw-r--r--src/core/ndisc/nm-ndisc.c102
-rw-r--r--src/core/ndisc/nm-ndisc.h7
-rw-r--r--src/core/nm-act-request.c38
-rw-r--r--src/core/nm-act-request.h8
-rw-r--r--src/core/nm-dhcp-config.c58
-rw-r--r--src/core/nm-dhcp-config.h2
-rw-r--r--src/core/nm-dispatcher.c139
-rw-r--r--src/core/nm-dispatcher.h6
-rw-r--r--src/core/nm-iface-helper.c20
-rw-r--r--src/core/nm-ip-config.c6
-rw-r--r--src/core/nm-ip4-config.h2
-rw-r--r--src/core/nm-ip6-config.h2
-rw-r--r--src/core/nm-manager.c2
-rw-r--r--src/core/nm-policy.c11
-rw-r--r--src/core/ppp/nm-ppp-manager-call.c18
-rw-r--r--src/core/ppp/nm-ppp-manager-call.h6
-rw-r--r--src/core/ppp/nm-ppp-manager.c171
-rw-r--r--src/core/ppp/nm-ppp-manager.h3
-rw-r--r--src/core/ppp/nm-ppp-plugin-api.h6
-rw-r--r--src/core/systemd/meson.build2
-rw-r--r--src/core/systemd/nm-sd.h1
-rw-r--r--src/core/systemd/src/libsystemd-network/sd-ipv4acd.c555
-rw-r--r--src/core/systemd/src/libsystemd-network/sd-ipv4ll.c357
-rw-r--r--src/core/systemd/src/systemd/sd-ipv4acd.h61
-rw-r--r--src/core/systemd/src/systemd/sd-ipv4ll.h63
-rw-r--r--src/core/vpn/nm-vpn-connection.c601
-rwxr-xr-xtools/run-nm-test.sh1
68 files changed, 4391 insertions, 6512 deletions
diff --git a/.gitignore b/.gitignore
index 22f745efe9..da3032c3d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -233,7 +233,6 @@ test-*.trs
/src/core/NetworkManager-all-sym
/src/core/NetworkManager.ver
/src/core/devices/bluetooth/tests/nm-bt-test
-/src/core/devices/tests/test-acd
/src/core/devices/tests/test-lldp
/src/core/devices/wifi/tests/test-devices-wifi
/src/core/devices/wwan/tests/test-service-providers
@@ -399,6 +398,7 @@ test-*.trs
/src/NetworkManager
/src/NetworkManager-all-sym
/src/NetworkManager.ver
+/src/core/devices/tests/test-acd
/src/core/initrd/nm-initrd-generator
/src/core/initrd/tests/test-cmdline-reader
/src/core/initrd/tests/test-dt-reader
diff --git a/Makefile.am b/Makefile.am
index 5b99dc98a4..02a01c19e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2313,8 +2313,6 @@ src_core_libnm_systemd_core_la_SOURCES = \
src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c \
src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c \
src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c \
- src/core/systemd/src/libsystemd-network/sd-ipv4acd.c \
- src/core/systemd/src/libsystemd-network/sd-ipv4ll.c \
src/core/systemd/src/libsystemd-network/sd-lldp.c \
src/core/systemd/src/libsystemd/sd-event/event-source.h \
src/core/systemd/src/libsystemd/sd-event/event-util.c \
@@ -2332,8 +2330,6 @@ src_core_libnm_systemd_core_la_SOURCES = \
src/core/systemd/src/systemd/sd-dhcp6-option.h \
src/core/systemd/src/systemd/sd-event.h \
src/core/systemd/src/systemd/sd-id128.h \
- src/core/systemd/src/systemd/sd-ipv4acd.h \
- src/core/systemd/src/systemd/sd-ipv4ll.h \
src/core/systemd/src/systemd/sd-lldp.h \
src/core/systemd/src/systemd/sd-ndisc.h \
$(NULL)
@@ -2423,8 +2419,6 @@ src_core_libNetworkManager_la_SOURCES = \
src/core/nm-checkpoint-manager.c \
src/core/nm-checkpoint-manager.h \
\
- src/core/devices/nm-acd-manager.c \
- src/core/devices/nm-acd-manager.h \
src/core/devices/nm-lldp-listener.c \
src/core/devices/nm-lldp-listener.h \
src/core/devices/nm-device.c \
@@ -4253,20 +4247,14 @@ src_core_devices_tests_ldflags = \
check_programs += \
src/core/devices/tests/test-lldp \
- src/core/devices/tests/test-acd
+ $(NULL)
src_core_devices_tests_test_lldp_CPPFLAGS = $(src_core_cppflags_test)
src_core_devices_tests_test_lldp_LDFLAGS = $(src_core_devices_tests_ldflags)
src_core_devices_tests_test_lldp_LDADD = \
src/core/libNetworkManagerTest.la
-src_core_devices_tests_test_acd_CPPFLAGS = $(src_core_cppflags_test)
-src_core_devices_tests_test_acd_LDFLAGS = $(src_core_devices_tests_ldflags)
-src_core_devices_tests_test_acd_LDADD = \
- src/core/libNetworkManagerTest.la
-
$(src_core_devices_tests_test_lldp_OBJECTS): $(src_libnm_core_public_mkenums_h)
-$(src_core_devices_tests_test_acd_OBJECTS): $(src_libnm_core_public_mkenums_h)
EXTRA_DIST += \
src/core/devices/tests/meson.build
diff --git a/WIP.txt b/WIP.txt
new file mode 100644
index 0000000000..3f3bd353f9
--- /dev/null
+++ b/WIP.txt
@@ -0,0 +1,15 @@
+The following files have changes since the last rebase,
+that need re-review. They probably also don't compile
+and are incomplete:
+
+ > src/core/devices/nm-device.c
+ > src/core/devices/nm-device.h
+ > src/core/nm-act-request.c
+ > src/core/nm-act-request.h
+ > src/core/nm-iface-helper.c
+ > src/core/nm-ip-config.c
+ > src/core/nm-ip4-config.h
+ > src/core/nm-ip6-config.h
+ > src/core/nm-manager.c
+ > src/core/nm-policy.c
+ > src/core/vpn/nm-vpn-connection.c
diff --git a/src/core/README.l3cfg.md b/src/core/README.l3cfg.md
new file mode 100644
index 0000000000..100ce012ea
--- /dev/null
+++ b/src/core/README.l3cfg.md
@@ -0,0 +1,332 @@
+L3Cfg Rework
+============
+
+NMDevice is complex. Together with NMManager, NMDevice does too much.
+
+The goal is to rework the IP configuration (Layer 3) to be a more separate
+part of the code that is better maintainable, easier to understand and
+extend and more correct.
+
+Current Situation
+-----------------
+
+- [NMManager](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-manager.c):
+ this is the main object (a singleton) that drives most things.
+ Among many other things, it creates NMDevice instances and coordinates.
+
+- [NMDevice](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c):
+ this represents a device. This is a subclass of NMDBusObject,
+ it is thus directly exported on D-Bus (as D-Bus objects like
+ `/org/freedesktop/NetworkManager/Devices/1`).
+ It also manages all aspects of the device. It has an overall state
+ (`NM_DEVICE_STATE`) but lots of more specific states (e.g. current state
+ of DHCP configuration). As always, the hardest part in programming are
+ stateful objects, and NMDevice has *a lot* of state. The code is huge and
+ hard to understand and the class has (too) many responsibilities. \
+ \
+ NMDevice also has subclasses, which are determined based on the "device type". That
+ means, there are subclasses like NMDeviceEthernet and NMDeviceBridge. As such, the
+ subclasses also export additional D-Bus interfaces. These subclasses also handle
+ the Layer 2 specific aspects of the device. For this aspect, delegation probably
+ would have been a better choice. On the other hand, IP configuration is almost entirely
+ managed by the parent class. Which is good, because the IP configuration is common to all
+ device types, but is bad because NMDevice already does so many things.
+
+- [NMIP4Config](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-ip4-config.c) (and NMIP6Config):
+ these are also subclasses of NMDBusObject
+ and exported on D-Bus on paths like `/org/freedesktop/NetworkManager/IP4Config/1`.
+ The device's `IP4Config` property refers to these objects. They contain
+ the runtime IP information of that device. I don't think these objects
+ should exist on the D-Bus API, as NMDevice could directly expose these properties.
+ But for historic reasons, such is our D-Bus API.
+ Other than that, NMIP4Config objects are also used internally for tracking
+ IP configuration. For example, [when](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dhcp/nm-dhcp-nettools.c#L563)
+ we receive a DHCP lease, we construct a NMIP4Config object with the addresses, DNS settings,
+ and so on. These
+ instances are then [tracked by](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L519)
+ NMDevice, and [merged](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L8928)
+ into an instance that is then exposed on D-Bus. As such, this class has two
+ mostly independent purposes.
+
+- [NMDhcpClient](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dhcp/nm-dhcp-client.c):
+ our DHCP "library". It's a simple object with a clear API that
+ abstracts most of the complexity of handling DHCP. But still, NMDevice
+ needs to drive the DHCP client instance. Meaning, it needs to create (start) and stop
+ them and hook up signals for changes (new lease) and timeout. This is mostly
+ fine and unavoidable. The point is that while specific tasks are well abstracted
+ (like the details of DHCP), there is still some state in NMDevice that is related
+ to manage these tasks. DHCP is one of many such tasks, like also
+ link local addresses, SLAAC or LLDP.
+ This leads to the increased complexity of NMDevice, which manages a large variety
+ of such tasks.
+
+### Problems:
+
+1. first the sheer code size of [nm-device.c](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L19030).
+ It's hard to understand and maintain, and this results in misbehaviours. Also, features that should be easy to implement
+ are not. Also, there are inefficiencies that are hard to fix.
+
+2. NMDevice and NMIP4Config are both exported on D-Bus while having other responsibilities.
+ Being subclasses of NMDBusObject, they are glued to the D-Bus API. For example, NMIP4Config is
+ also used for other purposes (for tracking IP configuration internally).
+
+3. NMDevice simply does too much. IP configuration should be a separate, encapsulated
+ API to make allow NMDevice to be smaller and the IP configuration part better
+ testable, understandable and smaller too.
+
+4. in the current model, NMDevice can be related to zero, one or two ifindexes. For example,
+ for ethernet devices, there is commonly only one actual netdev device (and one ifindex).
+ For OVS devices, there is no ifindex. For NMDeviceModem or NMDeviceBluetooth there is
+ a NMDevice instance that has initially no ifindex (it represents the tty serial port
+ or the bluetooth device) but during activation it gets and ip ifindex. With PPPoE,
+ the ethernet device can even have two ifindexes (one for the underlying ethernet and
+ one for the PPP device). That is all utterly confusing, inconsistent and limited.
+ For example, not all interfaces you see in `ip link` can be found in the D-Bus API.
+ The D-Bus API also does not give access to the ifindex (which is the real identifier
+ for a netdev devices). It only exposes the IpInterface name. That should be improved too,
+ but even such seemingly simple things are not done for years, because it's not trivially
+ clear what the right ifindex is.
+ Also a device instance on D-Bus significantly changes its meaning when it activates/deactivates
+ and it starts/stops being responsible for an ifindex.
+ In the future there should be devices that represent exactly one netdev device (an ifindex)
+ and devices that don't have an ifindex. That is follow up work and hinted by
+ [rhbz#1066703](https://bugzilla.redhat.com/show_bug.cgi?id=1066703). But simplifying
+ the IP configuration is a requisite before addressing that rework.
+ With this we will have controller and controlled devices. That means, a controller devices
+ (that for example represents a bluetooth device) will need to configure IP address on the
+ controlled IP device. That would be doable by injecting the IP config on that device,
+ but as the device already does so much, it would be better if this would be a separate
+ IP configuration manager for that ifindex.
+
+5. NMIP4Config exports properties on D-Bus like [AddressData](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/introspection/org.freedesktop.NetworkManager.IP4Config.xml#L26).
+ which are the currently configured IP addresses. These should be directly obtained
+ from the NMPlatform cache, which contains the correct list of addresses as kernel
+ exposes them via rtnetlink. Instead, whenever there are changes in platform we
+ [generate](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14223)
+ an NMIP4Config instance, then we merge, intersect and subtract this captured information
+ with the IP configs we want to configure. Finally we merge them together again
+ and sync the result to platform. This is bad, wrong and inefficient.
+ We must not mix "what is configured" with "what we want to configure". The current
+ approach also re-generates these IP config instance whenever something in platform changes.
+ That does not scale. If we have any hope to handle thousands of routes, this needs to change.
+
+6. The NMIP4Config objects are mutable, and they are heavily mutated. When we create an NMIP4Config
+ instance that represent a DHCP lease, we will [subtract](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14236)
+ addresses that were externally removed. That is wrong, because during a reapply we
+ will need to know these addresses again. The solution for that is not to mutate this
+ data, but track whether IP addresses are removed separately.
+
+7. NMDevice also does ACD, but it can only do it for addresses received via DHCP.
+ It implicitly also does ACD for IPv4LL, but that is via using the n_ipv4ll library.
+ It would be good to have an option that we can configure IPv4LL for any address.
+ Also, if you manually configure an address like 192.168.2.5 (for which we don't do
+ ACD) and the same address is obtained via DHCP, then doing ACD for the address is wrong.
+ There needs to be link-wide view of the addresses, and not only looking at individual
+ addresses when deciding to do ACD.
+
+8. As IP configuration is done by NMDevice, VPN connections have limited capabilities
+ in this regard.
+ When a VPN has IP addresses, then it injects them into NMDevice by
+ [providing](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L13696)
+ an NMIP4Config. However, that means VPNs cannot do DHCP or IPv4LL, because it can
+ only inject known configuration. That would be very useful for example with a tap
+ device with openvpn. The real problem here is that NMVpnConnection are
+ treated special, when they should be more like devices. That should be reworked in the future,
+ by reworking VPN plugins. Regardless, having IP configuration handled by NMDevice is limiting.
+
+9. NetworkManager currently supports `ipv4.method` which can be "manual", "disabled" or
+ "auto". This scheme does not allow for example to enable IPv4LL together with DHCPv4.
+ As a special case, you can configure `ipv4.method=auto` together with static
+ addresses in `ipv4.addresses`, so combining DHCP and static addressing works. But in general,
+ this scheme is limited. In the future we should have more flexible schemes, where
+ addressing methods can be independently enabled or disabled. Also, we currently
+ have `ipv4.may-fail`, but that is limited as well. For example,
+ `ipv4.may-fail=yes` and `ipv6.may-fail=yes` still means that at least one of the
+ address families must succeed. That makes sense for certain use cases, but it
+ means, you cannot have truly best-effort, opportunistic DHCP with this way.
+ As workaround for that there is `ipv4.dhcp-timeout=infinity`. In
+ general it is not only useful to enable methods independently, we also configure
+ independently whether they are required or optional (and possibly, that they are optional
+ but at least one of several optional methods must succeed). Anyway. The point
+ is there is a need to make IP configuration more flexible. Currently it is not.
+ Such a seemingly simple extension would be surprisingly difficult to implement
+ because [the code](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L6616) is
+ all over the place. The way how NMDevice tracks the overall activation state is
+ hard to understand. This should be improved and possibly could be improved in a
+ smaller refactoring effort. But instead of a smaller effort, we will use the big hammer
+ with L3Cfg rework.
+
+10. There are two classes NMIP4Config and NMIP6Config. Handling both address families is
+ commonly similar, so there is lot of similar code in both. They should be unified
+ so that similar code can handle both address families.
+
+
+Solution and Future
+-------------------
+
+NML3Cfg work is supposed to simplify some part of NMDevice: the part related to
+IP configuration. This is a huge rework of a core part of NetworkManager. Arguably,
+some parts maybe could be done more evolutionary, but the fundamental problems require
+to rip out NMIP4Config and replace it by something better. Doing that is a large rework
+that changes NMDevice heavily. That is also the opportunity to get the smaller issues
+right.
+
+There is already a new class [NML3Cfg](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.h#L141)
+(currently unused). An NML3Cfg instance is responsible for handling IP configuration
+of an ifindex. Consequently, we can ask NMNetns to [get](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-netns.c#L142)
+(or create) a NML3Cfg instance for an ifindex.
+The idea is that there can be multiple users (NMDevice and NMVpnConnection and future controller devices)
+that use the same NML3Cfg instance. Especially with a future rework of NMDevice where
+a NMDevice only manages one ifindex (or none), there is a need that multiple
+devices manage the IP configuration on the same device. Independent users can cooperate
+to configure IP configuration on the same device. Already now with Libreswan VPN, where the VPN "injects"
+its NMIP4Config in NMDevice. Or with PPPoE, where the NMDeviceEthernet is both about IP configuration
+for the PPPoE device.
+
+There is also a new class [NML3ConfigData](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3-config-data.h).
+This replaces some aspect of NMIP4Config/NMIP6Config. A NML3ConfigData object is immutable and has no real logic
+(or state). It has some "logic", like comparing two NML3ConfigData instances, logging it, or merging two (immutable)
+instances into a new instance. But as the class is immutable, that logic is rather simple. This class is
+used to track information. As it's immutable, anybody who is interested can keep a reference
+for it's own purpose. For example, NMDhcpClient will generate a NML3ConfigData with the information
+of the lease. It may keep the reference, but it will also tell NMDevice about it. The NMDevice
+will then itself tell NML3Cfg to accept this configuration. This works by calling
+[add()/remove()](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2654).
+One NML3ConfigData can also track both IPv4 and IPv6 information. It's a general set of IP related
+configuration, that has some address specific properties. Those are then duplicated for both address
+families and implemented in a way to minimize code duplication and encourage to treat them the same.
+As this replaces an aspect of NMIP4Config, NMIP4Config can focus on it's other purpose: to expose data on D-Bus.
+
+What NML3Cfg then does, is to merge all NML3ConfigData, and "commit" it to platform. Thereby it knows
+which addresses it configured the last time (if they no longer are to be configured, they must be removed).
+This is done [here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3442).
+
+As independent users should be able to cooperate, it is not appropriate that they call "commit".
+Instead, they set a commit type ([here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3476),
+and whenever something changes, NML3Cfg knows the aggregated commit type. That is necessary
+because when we activate a device, we may want to preserve the existing IP configuration (e.g. after
+a restart of NetworkManager). During that time is the NML3Cfg instance set to a reduced commit
+mode (ASSUME).
+
+NML3Cfg will also handle IPv4 ACD. Any user of NML3Cfg registers/unregisters NML3ConfigData instances
+that should be configured. Thereby they also say whether ACD should be done for the IPv4 addresses.
+NML3Cfg then keeps state for each IPv4 address, whether ACD should be performed, and whether the
+address is ready to be configured. NML3Cfg does not do DHCP or similar. That is still the responsibility
+of NMDevice to run a NMDhcpClient. But it does run ACD, because whether to perform ACD on an address
+requires a holistic view of all addresses of that interface. For example, if you configure a static
+IP address 192.168.2.5 (with ACD disabled) and you also get the same address via DHCP, then ACD should
+not performed for that address (even if the user configured ACD with DHCP). Of course, that is a very
+unlikely example. More likely is that NetworkManager is restarted and it leaves the addresses (that passed
+ACD) configured. After restart, DHCP finds the same addresses and no new ACD should be performed. This shows
+that the ACD state depends all the IP addresses on an interface,
+and thus it's done by NML3Cfg. The API for this is very simple. Users enable/disable ACD during nm_l3cfg_add_config()
+and receive events like [NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L303).
+Another advantage is that ACD now works for any kinds of addresses. Currently it only works for addresses
+from DHCP and link local addresses.
+
+NML3Cfg does not implement or drive DHCP. However, as it already does ACD it gained it's own IPv4LL
+"library": [NML3IPv4LL](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L3624).
+This will replace nettools' n-ipv4ll library, because that library also does ACD internally, while we want
+to use the holistic view that NML3Cfg has. What this means, is that the user (NMDevice)
+can request a NML3IPv4LL handle from the NML3Cfg instance, and it just does it with a simple API.
+All the user might do is to enable/disable the handle and to react to signals (if it cares to find
+out whether IPv4LL fails).
+
+The general parts of NML3Cfg are already implemented. It has unit tests and can be tested independently.
+You might note that NML3Cfg is not trivial already, but the API that it provides is as simple as possible:
+create immutable NML3ConfigData instance, and add/remove them. Optionally, handle the ACD events and
+listen to some events. The complexity that NML3Cfg has, will lead in the same amount simplify NMDevice.
+
+What is missing is NMDevice using this new API. Instead of creating and tracking NMIP4Config instances,
+it needs to track NML3ConfigData instances. In principle that sounds simple, in practice that changes
+large part of "nm-device.c".
+
+Thereby also the state machine for NM_DEVICE_STATE will be improved. It's anyway a rewrite. This will lay the
+groundwork for more flexible configuration of IP methods, with different failure modes (opportunistic or
+mandatory).
+
+What then also should be easier, to combine IPv4LL with other addressing methods. In Windows AFAIK, if you
+don't get a DHCP address it will configure a IPv4LL address. That is also what RFC suggests, but which we
+currently don't support.
+
+In general, change the way how external IP addresses/routes are tracked. This merge, intersect, subtract
+approach does not perform well. Currently we react on signals and it's hard to understand what happens
+in response to that, or whether it's really the correct thing to do. See yourself starting from
+[here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/devices/nm-device.c#L14214).
+
+### DHCP
+
+Currently, when NMDhcpClient receives a lease, it emits a signal with two things: the NMIP4Config
+instance (containing addresses, routes, DNS settings and other information for later use), and a string
+dictionary with the DHCP lease options (they are mainly used to expose them on D-Bus). The latter is
+immutable (meaning, it's not changed afterwards). That does not significantly change with L3Cfg. The
+difference is that instead of NMIP4Config a NML3ConfigData instance gets created. That instance then
+references the (immutable) strdict. With that, any part of the code that has access to the NML3ConfigData,
+also has access to the lease options. So instead of two separate
+pieces of information, the result of a lease event will only be a NML3ConfigData instance (which internally
+tracks the strdict with the DHCP lease options).
+
+Later, when NML3Cfg configures an interface, it takes all NML3ConfigData instances that were added to
+it, and merges them. [Currently](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3-config-data.c#L2693),
+the merged data will not contain the lease information, but it's probably not needed anyway.
+
+If it would be needed, the question is what happens if multiple lease informations are present
+during the merge. Duplicate leases would not commonly happen, but in general, the merging algorithm
+needs to take into account priorities and conflicting data.
+That is done by users who call [add](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2658)
+to provide a priority for the NML3ConfigData instance.
+Later, the instances get sorted by priority and merging is smart to take that into account
+([here](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/nm-l3cfg.c#L2983)).
+
+Also, we currently inject the route-metric and table into the generated NMIP4Config.
+Those settings come from the connection profiles and not from DHCP. We will avoid that
+by allowing the routes in NML3ConfigData to be marked as metric\_any and table\_any.
+That way,the NML3ConfigData is independent (and immutable) with respect to those settings.
+The same happens for example with PPP, where the modem starts PPP, and currently the
+route and metric needs to be passed several layers down. But worst, those settings
+can change during reapply. Currently that means we need to hack NMIP4Config with
+those changes. Later, we will only tell NML3Cfg to track the NML3ConfigData with
+different settings.
+
+### DNS
+
+DNS information is currently set in the NMIP4Config instances. That happens for example with the DNS information
+from a DHCP lease, but also with the static DNS settings from the connection profile. Later, the same information
+will packed in NML3ConfigData.
+
+One nice difference is again the immutability. Currently, NMDnsManager keeps a reference to all relevant NMIP4Config instances,
+but as they are mutable, it needs to [subscribe](https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/blob/6b64fac06d2f6e0d9fa530ebb1ab28d53a1c5d03/src/core/dns/nm-dns-manager.c#L275)
+to changes. Later, when a NML3ConfigData instance "changes", it means it was
+replaced by a different one and NMDnsManager needs to update its list of tracked NML3ConfigData. I find that
+cleaner, because adding and removal to the list of NMIP4Config/NML3ConfigData happens anyway and needs to be handled.
+
+
+Related Bugs
+------------
+
+* Main bug:
+
+ - [rh#1868254](https://bugzilla.redhat.com/show_bug.cgi?id=1868254):
+ "refactor NetworkManager's IP configuration done by NMDevice"
+
+* Follow up but to improve model of devices:
+
+ - [rh#1066703](https://bugzilla.redhat.com/show_bug.cgi?id=1066703):
+ "\[RFE\] Handle parent/child relationships more cleanly"
+
+* Flexible IP methods:
+
+ - [rh#1791624](https://bugzilla.redhat.com/show_bug.cgi?id=1791624):
+ "NetworkManager must not remove used bridge"
+
+* Improving performance issues, this will lay ground work:
+
+ - [rh#1847125](https://bugzilla.redhat.com/show_bug.cgi?id=1847125):
+ "\[RFE\] Improve 20% performance on creating 1000 bridge over 1000 VLANs"
+
+ - [rh#1861527](https://bugzilla.redhat.com/show_bug.cgi?id=1861527):
+ "Excessive memory and CPU usage on a router with IPv6 BGP feed"
+
+ - [rh#1753677](https://bugzilla.redhat.com/show_bug.cgi?id=1753677):
+ "High cpu usage while non-controlled interface is mangling tc filters"
+
diff --git a/src/core/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c
index dcc1e0e469..0ca959e40e 100644
--- a/src/core/devices/adsl/nm-device-adsl.c
+++ b/src/core/devices/adsl/nm-device-adsl.c
@@ -15,7 +15,6 @@
#include <unistd.h>
#include <stdlib.h>
-#include "nm-ip4-config.h"
#include "devices/nm-device-private.h"
#include "libnm-platform/nm-platform.h"
#include "ppp/nm-ppp-manager-call.h"
@@ -434,19 +433,30 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
NMDevice *device = NM_DEVICE(user_data);
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ if (addr_family != AF_INET)
+ return;
+
+ if (!nm_device_activate_ip4_state_in_conf(device)) {
+ /* Ignore PPP events that come in after initial configuration */
+ return;
+ }
+
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
}
static NMActStageReturn
-act_stage3_ip4_config_start(NMDevice * device,
- NMIP4Config ** out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip4_config_start(NMDevice * device,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
NMDeviceAdsl * self = NM_DEVICE_ADSL(device);
NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self);
@@ -476,14 +486,6 @@ act_stage3_ip4_config_start(NMDevice * device,
priv->ppp_manager = nm_ppp_manager_create(ppp_iface, &err);
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
-
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
@@ -509,23 +511,23 @@ act_stage3_ip4_config_start(NMDevice * device,
G_CALLBACK(ppp_ifindex_set),
self);
g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
if (addr_family == AF_INET)
- return act_stage3_ip4_config_start(device, (NMIP4Config **) out_config, out_failure_reason);
+ return act_stage3_ip4_config_start(device, out_l3cd, out_failure_reason);
return NM_DEVICE_CLASS(nm_device_adsl_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static void
@@ -537,7 +539,7 @@ adsl_cleanup(NMDeviceAdsl *self)
g_signal_handlers_disconnect_by_func(priv->ppp_manager,
G_CALLBACK(ppp_state_changed),
self);
- g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_ip4_config), self);
+ g_signal_handlers_disconnect_by_func(priv->ppp_manager, G_CALLBACK(ppp_new_config), self);
nm_ppp_manager_stop(priv->ppp_manager, NULL, NULL, NULL);
g_clear_object(&priv->ppp_manager);
}
diff --git a/src/core/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c
index c7f76a5ab8..6485c459c8 100644
--- a/src/core/devices/bluetooth/nm-device-bt.c
+++ b/src/core/devices/bluetooth/nm-device-bt.c
@@ -25,7 +25,6 @@
#include "settings/nm-settings-connection.h"
#include "nm-utils.h"
#include "nm-bt-error.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "devices/wwan/nm-modem-manager.h"
@@ -550,11 +549,20 @@ device_state_changed(NMDevice * device,
}
static void
-modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data)
+modem_new_config(NMModem * modem,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error,
+ gpointer user_data)
{
NMDeviceBt *self = NM_DEVICE_BT(user_data);
NMDevice * device = NM_DEVICE(self);
+ if (addr_family != AF_INET)
+ return;
+
g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE);
if (error) {
@@ -565,7 +573,8 @@ modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpoi
return;
}
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
}
static void
@@ -690,7 +699,7 @@ modem_try_claim(NMDeviceBt *self, NMModem *modem)
g_signal_connect(modem, NM_MODEM_PPP_STATS, G_CALLBACK(ppp_stats), self);
g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self);
g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self);
- g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self);
+ g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self);
g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self);
g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self);
g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self);
@@ -1002,10 +1011,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE(device);
@@ -1023,7 +1032,7 @@ act_stage3_ip_config_start(NMDevice * device,
}
return NM_DEVICE_CLASS(nm_device_bt_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static void
diff --git a/src/core/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c
deleted file mode 100644
index 995abacded..0000000000
--- a/src/core/devices/nm-acd-manager.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 - 2018 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-acd-manager.h"
-
-#include <netinet/in.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <linux/if_ether.h>
-
-#include "libnm-platform/nm-platform.h"
-#include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "n-acd/src/n-acd.h"
-
-/*****************************************************************************/
-
-typedef enum {
- STATE_INIT,
- STATE_PROBING,
- STATE_PROBE_DONE,
- STATE_ANNOUNCING,
-} State;
-
-typedef struct {
- in_addr_t address;
- gboolean duplicate;
- NAcdProbe *probe;
-} AddressInfo;
-
-struct _NMAcdManager {
- int ifindex;
- guint8 hwaddr[ETH_ALEN];
- State state;
- GHashTable *addresses;
- guint completed;
- NAcd * acd;
- GSource * event_source;
-
- NMAcdCallbacks callbacks;
- gpointer user_data;
-};
-
-/*****************************************************************************/
-
-#define _NMLOG_DOMAIN LOGD_IP4
-#define _NMLOG_PREFIX_NAME "acd"
-#define _NMLOG(level, ...) \
- G_STMT_START \
- { \
- char _sbuf[64]; \
- \
- nm_log((level), \
- _NMLOG_DOMAIN, \
- self && self->ifindex > 0 \
- ? nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex) \
- : NULL, \
- NULL, \
- "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- _NMLOG_PREFIX_NAME, \
- self ? nm_sprintf_buf(_sbuf, "[%p,%d]", self, self->ifindex) \
- : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
- } \
- G_STMT_END
-
-/*****************************************************************************/
-
-static const char *
-_acd_event_to_string(unsigned int event)
-{
- switch (event) {
- case N_ACD_EVENT_READY:
- return "ready";
- case N_ACD_EVENT_USED:
- return "used";
- case N_ACD_EVENT_DEFENDED:
- return "defended";
- case N_ACD_EVENT_CONFLICT:
- return "conflict";
- case N_ACD_EVENT_DOWN:
- return "down";
- }
- return NULL;
-}
-
-#define ACD_EVENT_TO_STRING_BUF_SIZE 50
-
-static const char *
-_acd_event_to_string_buf(unsigned event, char buffer[static ACD_EVENT_TO_STRING_BUF_SIZE])
-{
- const char *s;
-
- s = _acd_event_to_string(event);
- if (s)
- return s;
-
- g_snprintf(buffer, ACD_EVENT_TO_STRING_BUF_SIZE, "(%u)", event);
- return buffer;
-}
-
-static const char *
-acd_error_to_string(int error)
-{
- if (error < 0)
- return nm_strerror_native(-error);
-
- switch (error) {
- case _N_ACD_E_SUCCESS:
- return "success";
- case N_ACD_E_PREEMPTED:
- return "preempted";
- case N_ACD_E_INVALID_ARGUMENT:
- return "invalid argument";
- }
-
- g_return_val_if_reached(NULL);
-}
-
-static int
-acd_error_to_nmerr(int error, gboolean always_fail)
-{
- if (error < 0)
- return -nm_errno_native(error);
-
- if (always_fail) {
- if (NM_IN_SET(error, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT))
- return -NME_UNSPEC;
- g_return_val_if_reached(-NME_UNSPEC);
- }
-
- /* so, @error is either zero (indicating success) or one
- * of the special status codes like N_ACD_E_*. In both cases,
- * return the positive value here. */
- if (NM_IN_SET(error, _N_ACD_E_SUCCESS, N_ACD_E_PREEMPTED, N_ACD_E_INVALID_ARGUMENT))
- return error;
-
- g_return_val_if_reached(error);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_acd_manager_add_address:
- * @self: a #NMAcdManager
- * @address: an IP address
- *
- * Add @address to the list of IP addresses to probe.
-
- * Returns: %TRUE on success, %FALSE if the address was already in the list
- */
-gboolean
-nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address)
-{
- AddressInfo *info;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(self->state == STATE_INIT, FALSE);
-
- if (g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address)))
- return FALSE;
-
- info = g_slice_new0(AddressInfo);
- info->address = address;
-
- g_hash_table_insert(self->addresses, GUINT_TO_POINTER(address), info);
-
- return TRUE;
-}
-
-static gboolean
-acd_event(int fd, GIOCondition condition, gpointer data)
-{
- NMAcdManager *self = data;
- NAcdEvent * event;
- AddressInfo * info;
- gboolean emit_probe_terminated = FALSE;
- char address_str[INET_ADDRSTRLEN];
- int r;
-
- if (n_acd_dispatch(self->acd))
- return G_SOURCE_CONTINUE;
-
- while (!n_acd_pop_event(self->acd, &event) && event) {
- char to_string_buffer[ACD_EVENT_TO_STRING_BUF_SIZE];
- gs_free char *hwaddr_str = NULL;
- gboolean check_probing_done = FALSE;
-
- switch (event->event) {
- case N_ACD_EVENT_READY:
- n_acd_probe_get_userdata(event->ready.probe, (void **) &info);
- info->duplicate = FALSE;
- if (self->state == STATE_ANNOUNCING) {
- /* fake probe ended, start announcing */
- r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE);
- if (r) {
- _LOGW("couldn't announce address %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, address_str),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- } else {
- _LOGD("announcing address %s",
- _nm_utils_inet4_ntop(info->address, address_str));
- }
- }
- check_probing_done = TRUE;
- break;
- case N_ACD_EVENT_USED:
- n_acd_probe_get_userdata(event->used.probe, (void **) &info);
- info->duplicate = TRUE;
- check_probing_done = TRUE;
- break;
- case N_ACD_EVENT_DEFENDED:
- n_acd_probe_get_userdata(event->defended.probe, (void **) &info);
- _LOGD("defended address %s from host %s",
- _nm_utils_inet4_ntop(info->address, address_str),
- (hwaddr_str =
- nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender)));
- break;
- case N_ACD_EVENT_CONFLICT:
- n_acd_probe_get_userdata(event->conflict.probe, (void **) &info);
- _LOGW("conflict for address %s detected with host %s on interface '%s'",
- _nm_utils_inet4_ntop(info->address, address_str),
- (hwaddr_str =
- nm_utils_hwaddr_ntoa(event->defended.sender, event->defended.n_sender)),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex));
- break;
- default:
- _LOGD("unhandled event '%s'", _acd_event_to_string_buf(event->event, to_string_buffer));
- break;
- }
-
- if (check_probing_done && self->state == STATE_PROBING
- && ++self->completed == g_hash_table_size(self->addresses)) {
- self->state = STATE_PROBE_DONE;
- emit_probe_terminated = TRUE;
- }
- }
-
- if (emit_probe_terminated) {
- if (self->callbacks.probe_terminated_callback) {
- self->callbacks.probe_terminated_callback(self, self->user_data);
- }
- }
-
- return G_SOURCE_CONTINUE;
-}
-
-static gboolean
-acd_probe_add(NMAcdManager *self, AddressInfo *info, guint64 timeout)
-{
- NAcdProbeConfig *probe_config;
- int r;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- r = n_acd_probe_config_new(&probe_config);
- if (r) {
- _LOGW("could not create probe config for %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return FALSE;
- }
-
- n_acd_probe_config_set_ip(probe_config, (struct in_addr){info->address});
- n_acd_probe_config_set_timeout(probe_config, timeout);
-
- r = n_acd_probe(self->acd, &info->probe, probe_config);
- if (r) {
- _LOGW("could not start probe for %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- n_acd_probe_config_free(probe_config);
- return FALSE;
- }
-
- n_acd_probe_set_userdata(info->probe, info);
- n_acd_probe_config_free(probe_config);
-
- return TRUE;
-}
-
-static int
-acd_init(NMAcdManager *self)
-{
- NAcdConfig *config;
- int r;
-
- if (self->acd)
- return 0;
-
- r = n_acd_config_new(&config);
- if (r)
- return r;
-
- n_acd_config_set_ifindex(config, self->ifindex);
- n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET);
- n_acd_config_set_mac(config, self->hwaddr, ETH_ALEN);
-
- r = n_acd_new(&self->acd, config);
- n_acd_config_free(config);
- return r;
-}
-
-/**
- * nm_acd_manager_start_probe:
- * @self: a #NMAcdManager
- * @timeout: maximum probe duration in milliseconds
- * @error: location to store error, or %NULL
- *
- * Start probing IP addresses for duplicates; when the probe terminates a
- * PROBE_TERMINATED signal is emitted.
- *
- * Returns: 0 on success or a negative NetworkManager error code (NME_*).
- */
-int
-nm_acd_manager_start_probe(NMAcdManager *self, guint timeout)
-{
- GHashTableIter iter;
- AddressInfo * info;
- gboolean success = FALSE;
- int fd, r;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(self->state == STATE_INIT, FALSE);
-
- r = acd_init(self);
- if (r) {
- _LOGW("couldn't init ACD for probing on interface '%s': %s",
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return acd_error_to_nmerr(r, TRUE);
- }
-
- self->completed = 0;
-
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info))
- success |= acd_probe_add(self, info, timeout);
-
- if (success)
- self->state = STATE_PROBING;
-
- nm_assert(!self->event_source);
- n_acd_get_fd(self->acd, &fd);
- self->event_source =
- nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, acd_event, self, NULL);
- g_source_attach(self->event_source, NULL);
-
- return success ? 0 : -NME_UNSPEC;
-}
-
-/**
- * nm_acd_manager_check_address:
- * @self: a #NMAcdManager
- * @address: an IP address
- *
- * Check if an IP address is duplicate. @address must have been added with
- * nm_acd_manager_add_address().
- *
- * Returns: %TRUE if the address is not duplicate, %FALSE otherwise
- */
-gboolean
-nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address)
-{
- AddressInfo *info;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(NM_IN_SET(self->state, STATE_INIT, STATE_PROBE_DONE), FALSE);
-
- info = g_hash_table_lookup(self->addresses, GUINT_TO_POINTER(address));
- g_return_val_if_fail(info, FALSE);
-
- return !info->duplicate;
-}
-
-/**
- * nm_acd_manager_announce_addresses:
- * @self: a #NMAcdManager
- *
- * Start announcing addresses.
- *
- * Returns: a negative NetworkManager error number or zero on success.
- */
-int
-nm_acd_manager_announce_addresses(NMAcdManager *self)
-{
- GHashTableIter iter;
- AddressInfo * info;
- int r;
- int fd;
- gboolean success = TRUE;
-
- r = acd_init(self);
- if (r) {
- _LOGW("couldn't init ACD for announcing addresses on interface '%s': %s",
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- return acd_error_to_nmerr(r, TRUE);
- }
-
- if (self->state == STATE_INIT) {
- /* n-acd can't announce without probing, therefore let's
- * start a fake probe with zero timeout and then perform
- * the announcement. */
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) {
- if (!acd_probe_add(self, info, 0))
- success = FALSE;
- }
- self->state = STATE_ANNOUNCING;
- } else if (self->state == STATE_ANNOUNCING) {
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- g_hash_table_iter_init(&iter, self->addresses);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &info)) {
- if (info->duplicate)
- continue;
- r = n_acd_probe_announce(info->probe, N_ACD_DEFEND_ONCE);
- if (r) {
- _LOGW("couldn't announce address %s on interface '%s': %s",
- _nm_utils_inet4_ntop(info->address, sbuf),
- nm_platform_link_get_name(NM_PLATFORM_GET, self->ifindex),
- acd_error_to_string(r));
- success = FALSE;
- } else
- _LOGD("announcing address %s", _nm_utils_inet4_ntop(info->address, sbuf));
- }
- }
-
- if (!self->event_source) {
- n_acd_get_fd(self->acd, &fd);
- self->event_source =
- nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, acd_event, self, NULL);
- g_source_attach(self->event_source, NULL);
- }
-
- return success ? 0 : -NME_UNSPEC;
-}
-
-static void
-destroy_address_info(gpointer data)
-{
- AddressInfo *info = (AddressInfo *) data;
-
- n_acd_probe_free(info->probe);
-
- g_slice_free(AddressInfo, info);
-}
-
-/*****************************************************************************/
-
-NMAcdManager *
-nm_acd_manager_new(int ifindex,
- const guint8 * hwaddr,
- guint hwaddr_len,
- const NMAcdCallbacks *callbacks,
- gpointer user_data)
-{
- NMAcdManager *self;
-
- g_return_val_if_fail(ifindex > 0, NULL);
- g_return_val_if_fail(hwaddr, NULL);
- g_return_val_if_fail(hwaddr_len == ETH_ALEN, NULL);
-
- self = g_slice_new0(NMAcdManager);
-
- if (callbacks)
- self->callbacks = *callbacks;
- self->user_data = user_data;
-
- self->addresses = g_hash_table_new_full(nm_direct_hash, NULL, NULL, destroy_address_info);
- self->state = STATE_INIT;
- self->ifindex = ifindex;
- memcpy(self->hwaddr, hwaddr, ETH_ALEN);
- return self;
-}
-
-void
-nm_acd_manager_free(NMAcdManager *self)
-{
- g_return_if_fail(self);
-
- if (self->callbacks.user_data_destroy)
- self->callbacks.user_data_destroy(self->user_data);
-
- nm_clear_pointer(&self->addresses, g_hash_table_destroy);
- nm_clear_g_source_inst(&self->event_source);
- nm_clear_pointer(&self->acd, n_acd_unref);
-
- g_slice_free(NMAcdManager, self);
-}
diff --git a/src/core/devices/nm-acd-manager.h b/src/core/devices/nm-acd-manager.h
deleted file mode 100644
index e8ef6f2b99..0000000000
--- a/src/core/devices/nm-acd-manager.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 - 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_ACD_MANAGER__
-#define __NM_ACD_MANAGER__
-
-#include <netinet/in.h>
-
-typedef struct _NMAcdManager NMAcdManager;
-
-typedef struct {
- void (*probe_terminated_callback)(NMAcdManager *self, gpointer user_data);
- GDestroyNotify user_data_destroy;
-} NMAcdCallbacks;
-
-NMAcdManager *nm_acd_manager_new(int ifindex,
- const guint8 * hwaddr,
- guint hwaddr_len,
- const NMAcdCallbacks *callbacks,
- gpointer user_data);
-
-void nm_acd_manager_free(NMAcdManager *self);
-
-gboolean nm_acd_manager_add_address(NMAcdManager *self, in_addr_t address);
-int nm_acd_manager_start_probe(NMAcdManager *self, guint timeout);
-gboolean nm_acd_manager_check_address(NMAcdManager *self, in_addr_t address);
-int nm_acd_manager_announce_addresses(NMAcdManager *self);
-
-NM_AUTO_DEFINE_FCN0(NMAcdManager *, _nm_auto_free_acdmgr, nm_acd_manager_free);
-#define nm_auto_free_acdmgr nm_auto(_nm_auto_free_acdmgr)
-
-#endif /* __NM_ACD_MANAGER__ */
diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c
index 638c9b6937..fae23a0d35 100644
--- a/src/core/devices/nm-device-ethernet.c
+++ b/src/core/devices/nm-device-ethernet.c
@@ -1135,13 +1135,24 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
NMDevice *device = NM_DEVICE(user_data);
- /* Ignore PPP IP4 events that come in after initial configuration */
- if (nm_device_activate_ip4_state_in_conf(device))
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NM_IP_CONFIG_CAST(config));
+ if (addr_family != AF_INET)
+ return;
+
+ if (!nm_device_activate_ip4_state_in_conf(device)) {
+ /* Ignore PPP IP4 events that come in after initial configuration */
+ return;
+ }
+
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
}
static NMActStageReturn
@@ -1163,14 +1174,6 @@ pppoe_stage3_ip4_config_start(NMDeviceEthernet *self, NMDeviceStateReason *out_f
priv->ppp_manager = nm_ppp_manager_create(nm_device_get_iface(device), &err);
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
-
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
@@ -1196,8 +1199,8 @@ pppoe_stage3_ip4_config_start(NMDeviceEthernet *self, NMDeviceStateReason *out_f
G_CALLBACK(ppp_ifindex_set),
self);
g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -1495,10 +1498,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_config,
+ NMDeviceStateReason * out_failure_reason)
{
NMSettingConnection *s_con;
const char * connection_type;
diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c
index b642d0d7de..fd974f8c32 100644
--- a/src/core/devices/nm-device-ppp.c
+++ b/src/core/devices/nm-device-ppp.c
@@ -7,7 +7,7 @@
#include "nm-device-ppp.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#include "nm-act-request.h"
#include "nm-device-factory.h"
#include "nm-device-private.h"
@@ -24,8 +24,8 @@
/*****************************************************************************/
typedef struct _NMDevicePppPrivate {
- NMPPPManager *ppp_manager;
- NMIP4Config * ip4_config;
+ NMPPPManager * ppp_manager;
+ const NML3ConfigData *l3cd_4;
} NMDevicePppPrivate;
struct _NMDevicePpp {
@@ -93,26 +93,31 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
NMDevice * device = NM_DEVICE(user_data);
NMDevicePpp * self = NM_DEVICE_PPP(device);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
+ if (addr_family != AF_INET)
+ return;
+
_LOGT(LOGD_DEVICE | LOGD_PPP, "received IPv4 config from pppd");
- if (nm_device_get_state(device) == NM_DEVICE_STATE_IP_CONFIG) {
- if (nm_device_activate_ip4_state_in_conf(device)) {
- nm_device_activate_schedule_ip_config_result(device,
- AF_INET,
- NM_IP_CONFIG_CAST(config));
- return;
- }
- } else {
- if (priv->ip4_config)
- g_object_unref(priv->ip4_config);
- priv->ip4_config = g_object_ref(config);
+ if (nm_device_get_state(device) != NM_DEVICE_STATE_IP_CONFIG) {
+ nm_l3_config_data_reset(&priv->l3cd_4, l3cd);
+ return;
}
+
+ if (!nm_device_activate_ip4_state_in_conf(device))
+ return;
+
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
}
static gboolean
@@ -150,18 +155,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
s_pppoe = nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE);
g_return_val_if_fail(s_pppoe, NM_ACT_STAGE_RETURN_FAILURE);
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
priv->ppp_manager = nm_ppp_manager_create(nm_setting_pppoe_get_parent(s_pppoe), &error);
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
- }
-
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
@@ -187,27 +184,27 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
G_CALLBACK(ppp_ifindex_set),
self);
g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
if (addr_family == AF_INET) {
NMDevicePpp * self = NM_DEVICE_PPP(device);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
- if (priv->ip4_config) {
- if (out_config)
- *out_config = g_steal_pointer(&priv->ip4_config);
+ if (priv->l3cd_4) {
+ if (out_l3cd)
+ *out_l3cd = g_steal_pointer(&priv->l3cd_4);
else
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
return NM_ACT_STAGE_RETURN_SUCCESS;
}
@@ -216,7 +213,7 @@ act_stage3_ip_config_start(NMDevice * device,
}
return NM_DEVICE_CLASS(nm_device_ppp_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static gboolean
@@ -268,7 +265,7 @@ dispose(GObject *object)
NMDevicePpp * self = NM_DEVICE_PPP(object);
NMDevicePppPrivate *priv = NM_DEVICE_PPP_GET_PRIVATE(self);
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
G_OBJECT_CLASS(nm_device_ppp_parent_class)->dispose(object);
}
diff --git a/src/core/devices/nm-device-private.h b/src/core/devices/nm-device-private.h
index 8675a699a3..ddd7b01003 100644
--- a/src/core/devices/nm-device-private.h
+++ b/src/core/devices/nm-device-private.h
@@ -42,8 +42,6 @@ enum NMActStageReturn {
#define NM_DEVICE_CAP_INTERNAL_MASK 0xc0000000
-void nm_device_arp_announce(NMDevice *self);
-
NMSettings *nm_device_get_settings(NMDevice *self);
NMManager *nm_device_get_manager(NMDevice *self);
@@ -74,8 +72,7 @@ void nm_device_set_firmware_missing(NMDevice *self, gboolean missing);
void nm_device_activate_schedule_stage1_device_prepare(NMDevice *device, gboolean do_sync);
void nm_device_activate_schedule_stage2_device_config(NMDevice *device, gboolean do_sync);
-void
-nm_device_activate_schedule_ip_config_result(NMDevice *device, int addr_family, NMIPConfig *config);
+void nm_device_activate_schedule_ip_config_result(NMDevice *device, int addr_family);
void nm_device_activate_schedule_ip_config_timeout(NMDevice *device, int addr_family);
@@ -119,8 +116,7 @@ nm_device_activate_ip6_state_done(NMDevice *self)
void nm_device_set_dhcp_anycast_address(NMDevice *device, const char *addr);
-gboolean nm_device_dhcp4_renew(NMDevice *device, gboolean release);
-gboolean nm_device_dhcp6_renew(NMDevice *device, gboolean release);
+gboolean nm_device_dhcp_renew(NMDevice *device, int addr_family, gboolean release);
void nm_device_recheck_available_connections(NMDevice *device);
@@ -136,7 +132,7 @@ void nm_device_queue_recheck_available(NMDevice * device,
NMDeviceStateReason available_reason,
NMDeviceStateReason unavailable_reason);
-void nm_device_set_dev2_ip_config(NMDevice *device, int addr_family, NMIPConfig *config);
+void nm_device_set_dev2_ip_config(NMDevice *device, int addr_family, const NML3ConfigData *l3cd);
gboolean nm_device_hw_addr_is_explict(NMDevice *device);
@@ -147,11 +143,7 @@ gboolean nm_device_sysctl_ip_conf_set(NMDevice * self,
const char *property,
const char *value);
-NMIP4Config *nm_device_ip4_config_new(NMDevice *self);
-
-NMIP6Config *nm_device_ip6_config_new(NMDevice *self);
-
-NMIPConfig *nm_device_ip_config_new(NMDevice *self, int addr_family);
+NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self);
NML3ConfigData *nm_device_create_l3_config_data(NMDevice *self);
diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c
index 3b426ef4c9..d25ab76bc0 100644
--- a/src/core/devices/nm-device-vlan.c
+++ b/src/core/devices/nm-device-vlan.c
@@ -112,7 +112,6 @@ parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_d
NM_PRINT_FMT_QUOTE_STRING(new_mac));
if (new_mac) {
nm_device_hw_addr_set(device, new_mac, "vlan-parent", TRUE);
- nm_device_arp_announce(device);
/* When changing the hw address the interface is taken down,
* removing the IPv6 configuration; reapply it.
*/
diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c
index ca552a2c8c..973e80101f 100644
--- a/src/core/devices/nm-device-wireguard.c
+++ b/src/core/devices/nm-device-wireguard.c
@@ -11,6 +11,7 @@
#include <linux/fib_rules.h>
#include "nm-setting-wireguard.h"
+#include "nm-l3-config-data.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-glib-aux/nm-secret-utils.h"
#include "nm-device-private.h"
@@ -1624,19 +1625,19 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
return ret;
}
-static NMIPConfig *
+static const NML3ConfigData *
_get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
{
- NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
- gs_unref_object NMIPConfig *ip_config = NULL;
- NMConnection * connection;
- NMSettingWireGuard * s_wg;
- guint n_peers;
- guint i;
- int ip_ifindex;
- guint32 route_metric;
- guint32 route_table_coerced;
- gboolean auto_default_route_enabled;
+ NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMConnection * connection;
+ NMSettingWireGuard * s_wg;
+ guint n_peers;
+ guint i;
+ int ip_ifindex;
+ guint32 route_metric;
+ guint32 route_table_coerced;
+ gboolean auto_default_route_enabled;
_auto_default_route_init(self);
@@ -1714,11 +1715,10 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
continue;
}
- if (!ip_config) {
- ip_config = nm_device_ip_config_new(NM_DEVICE(self), addr_family);
- nm_ip_config_set_config_flags(ip_config,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES,
- 0);
+ if (!l3cd) {
+ l3cd = nm_device_create_l3_config_data(NM_DEVICE(self));
+ nm_l3_config_data_set_flags(l3cd,
+ NM_L3_CONFIG_DAT_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES);
}
nm_utils_ipx_address_clear_host_address(addr_family, &addrbin, NULL, prefix);
@@ -1753,27 +1753,30 @@ _get_dev2_ip_config(NMDeviceWireGuard *self, int addr_family)
};
}
- nm_ip_config_add_route(ip_config, &rt.rx, NULL);
+ nm_l3_config_data_add_route(l3cd, addr_family, NULL, &rt.rx);
}
}
- return g_steal_pointer(&ip_config);
+ if (!l3cd)
+ return NULL;
+
+ return nm_l3_config_data_seal(g_steal_pointer(&l3cd));
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
- gs_unref_object NMIPConfig *ip_config = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
- ip_config = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
+ l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family);
- nm_device_set_dev2_ip_config(device, addr_family, ip_config);
+ nm_device_set_dev2_ip_config(device, addr_family, l3cd);
return NM_DEVICE_CLASS(nm_device_wireguard_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static guint32
@@ -1863,11 +1866,9 @@ can_reapply_change(NMDevice * device,
static void
reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new)
{
- NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
- NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
- gs_unref_object NMIPConfig *ip4_config = NULL;
- gs_unref_object NMIPConfig *ip6_config = NULL;
- NMDeviceState state = nm_device_get_state(device);
+ NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device);
+ NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
+ NMDeviceState state = nm_device_get_state(device);
NM_DEVICE_CLASS(nm_device_wireguard_parent_class)->reapply_connection(device, con_old, con_new);
@@ -1877,11 +1878,14 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne
}
if (state >= NM_DEVICE_STATE_IP_CONFIG) {
- ip4_config = _get_dev2_ip_config(self, AF_INET);
- ip6_config = _get_dev2_ip_config(self, AF_INET6);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_4 = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_6 = NULL;
+
+ l3cd_4 = _get_dev2_ip_config(self, AF_INET);
+ l3cd_6 = _get_dev2_ip_config(self, AF_INET6);
- nm_device_set_dev2_ip_config(device, AF_INET, ip4_config);
- nm_device_set_dev2_ip_config(device, AF_INET6, ip6_config);
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd_4);
+ nm_device_set_dev2_ip_config(device, AF_INET6, l3cd_6);
}
}
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index bfc3f55a1e..84bf11347d 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -33,6 +33,7 @@
#include "nm-device-private.h"
#include "nm-l3cfg.h"
#include "nm-l3-config-data.h"
+#include "nm-l3-ipv4ll.h"
#include "NetworkManagerUtils.h"
#include "nm-manager.h"
#include "libnm-platform/nm-platform.h"
@@ -64,7 +65,6 @@
#include "nm-config.h"
#include "c-list/src/c-list.h"
#include "dns/nm-dns-manager.h"
-#include "nm-acd-manager.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "systemd/nm-sd.h"
#include "nm-lldp-listener.h"
@@ -79,23 +79,14 @@
#include "nm-device-logging.h"
+//XXX
+NM_PRAGMA_WARNING_DISABLE("-Wunused-function")
+
/*****************************************************************************/
#define DEFAULT_AUTOCONNECT TRUE
-static guint32
-dhcp_grace_period_from_timeout(guint32 timeout)
-{
-#define DHCP_GRACE_PERIOD_MULTIPLIER 2U
-
- nm_assert(timeout > 0);
- nm_assert(timeout < G_MAXINT32);
-
- if (timeout < G_MAXUINT32 / DHCP_GRACE_PERIOD_MULTIPLIER)
- return timeout * DHCP_GRACE_PERIOD_MULTIPLIER;
-
- return G_MAXUINT32;
-}
+#define GRACE_PERIOD_MULTIPLIER 2U
#define CARRIER_WAIT_TIME_MS 6000
#define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000
@@ -114,6 +105,13 @@ typedef enum {
CLEANUP_TYPE_DECONFIGURE,
} CleanupType;
+typedef enum _nm_packed {
+ ADDR_METHOD_STATE_DISABLED,
+ ADDR_METHOD_STATE_PENDING,
+ ADDR_METHOD_STATE_GOOD,
+ ADDR_METHOD_STATE_FAILED,
+} AddrMethodState;
+
typedef struct {
CList lst_slave;
NMDevice *slave;
@@ -136,28 +134,40 @@ typedef struct {
NMOptionBool autoprobe;
} SriovOp;
-typedef void (*AcdCallback)(NMDevice *, NMIP4Config **, gboolean);
-
typedef enum {
/* The various NML3ConfigData types that we track explicitly. Note that
* their relative order matters: higher numbers in this enum means more
* important (and during merge overwrites other settings). */
+
L3_CONFIG_DATA_TYPE_LL_4,
+ L3_CONFIG_DATA_TYPE_LL_6,
+
+#define L3_CONFIG_DATA_TYPE_LL(IS_IPv4) \
+ ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_LL_4 : L3_CONFIG_DATA_TYPE_LL_6)
+
L3_CONFIG_DATA_TYPE_AC_6,
+ L3_CONFIG_DATA_TYPE_PD_6,
+
L3_CONFIG_DATA_TYPE_DHCP_4,
L3_CONFIG_DATA_TYPE_DHCP_6,
+
+#define L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4) \
+ ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_DHCP_4 : L3_CONFIG_DATA_TYPE_DHCP_6)
+
+ L3_CONFIG_DATA_TYPE_SHARED_4,
L3_CONFIG_DATA_TYPE_DEV_4,
L3_CONFIG_DATA_TYPE_DEV_6,
+
+#define L3_CONFIG_DATA_TYPE_DEV_X(IS_IPv4) \
+ ((IS_IPv4) ? L3_CONFIG_DATA_TYPE_DEV_4 : L3_CONFIG_DATA_TYPE_DEV_6)
+
L3_CONFIG_DATA_TYPE_SETTING,
+
_L3_CONFIG_DATA_TYPE_NUM,
_L3_CONFIG_DATA_TYPE_NONE,
} L3ConfigDataType;
-typedef struct {
- AcdCallback callback;
- NMDevice * device;
- NMIP4Config **configs;
-} AcdData;
+G_STATIC_ASSERT(NM_L3CFG_CONFIG_PRIORITY_IPV4LL == L3_CONFIG_DATA_TYPE_LL_4);
typedef enum {
HW_ADDR_TYPE_UNSET = 0,
@@ -174,18 +184,13 @@ typedef enum {
} FirewallState;
typedef struct {
- NMIPConfig *orig; /* the original configuration applied to the device */
- NMIPConfig *current; /* configuration after external changes. NULL means
- * that the original configuration didn't change. */
-} AppliedConfig;
-
-typedef struct {
NMDhcpClient *client;
NMDhcpConfig *config;
+ GSource * grace_source;
gulong state_sigid;
- guint grace_id;
bool grace_pending : 1;
bool was_active : 1;
+ bool is_bad : 1;
} DhcpData;
struct _NMDeviceConnectivityHandle {
@@ -257,6 +262,9 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice,
PROP_IP4_ADDRESS,
PROP_IP4_CONFIG,
PROP_DHCP4_CONFIG,
+
+#define PROP_DHCPX_CONFIG(IS_IPv4) ((IS_IPv4) ? PROP_DHCP4_CONFIG : PROP_DHCP6_CONFIG)
+
PROP_IP6_CONFIG,
PROP_DHCP6_CONFIG,
PROP_STATE,
@@ -290,8 +298,6 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDevice,
PROP_INTERFACE_FLAGS, );
typedef struct _NMDevicePrivate {
- bool in_state_changed;
-
guint device_link_changed_id;
guint device_ip_link_changed_id;
@@ -305,16 +311,7 @@ typedef struct _NMDevicePrivate {
NMDeviceStateReason reason;
} queued_state;
- union {
- struct {
- guint queued_ip_config_id_6;
- guint queued_ip_config_id_4;
- };
- guint queued_ip_config_id_x[2];
- };
-
GSList *pending_actions;
- GSList *dad6_failed_addrs;
NMDBusTrackObjPath parent_device;
@@ -331,15 +328,30 @@ typedef struct _NMDevicePrivate {
};
union {
+ NML3Cfg *const l3cfg;
+ NML3Cfg * l3cfg_;
+ };
+
+ NML3CfgCommitTypeHandle *l3cfg_commit_type;
+
+ union {
const int ifindex;
int ifindex_;
};
+
union {
const int ip_ifindex;
int ip_ifindex_;
};
- NMNetnsSharedIPHandle *shared_ip_handle;
+ union {
+ const NML3ConfigData * d;
+ const NML3ConfigData *const d_;
+ } l3cds[_L3_CONFIG_DATA_TYPE_NUM];
+
+ NMNetnsSharedIPHandle *shared4_ip_handle;
+
+ NMUtilsShareRules *shared4_rules;
int parent_ifindex;
@@ -362,9 +374,6 @@ typedef struct _NMDevicePrivate {
bool real : 1;
- bool update_ip_config_completed_v4 : 1;
- bool update_ip_config_completed_v6 : 1;
-
NMDeviceType type;
char * type_desc;
NMLinkType link_type;
@@ -378,6 +387,8 @@ typedef struct _NMDevicePrivate {
bool
hw_addr_perm_fake : 1; /* whether the permanent HW address could not be read and is a fake */
+ guint8 in_state_changed : 4;
+
NMUtilsStableType current_stable_id_type : 3;
bool nm_owned : 1; /* whether the device is a device owned and created by NM */
@@ -443,7 +454,7 @@ typedef struct _NMDevicePrivate {
gulong config_changed_id;
gulong ifindex_changed_id;
guint32 mtu;
- guint32 ip6_mtu;
+ guint32 ip6_mtu; /* FIXME(l3cfg) */
guint32 mtu_initial;
guint32 ip6_mtu_initial;
NMDeviceMtuSource mtu_source;
@@ -460,6 +471,14 @@ typedef struct _NMDevicePrivate {
gint64 carrier_wait_until_ms;
union {
+ struct {
+ NML3ConfigMergeFlags l3config_merge_flags_6;
+ NML3ConfigMergeFlags l3config_merge_flags_4;
+ };
+ NML3ConfigMergeFlags l3config_merge_flags_x[2];
+ };
+
+ union {
const NMDeviceSysIfaceState sys_iface_state;
NMDeviceSysIfaceState sys_iface_state_;
};
@@ -489,13 +508,19 @@ typedef struct _NMDevicePrivate {
bool ipv6ll_handle : 1; /* TRUE if NM handles the device's IPv6LL address */
bool ipv6ll_has : 1;
- bool ndisc_started : 1;
+ bool ac6_ndisc_started : 1;
+ bool ac6_ndisc_grace_pending : 1;
bool device_link_changed_down : 1;
bool concheck_rp_filter_checked : 1;
+ bool ll4_ipv4ll_ready : 1;
+ bool ll4_ipv4ll_failed : 1;
+
NMDeviceStageState stage1_sriov_state : 3;
+ GSource *ac6_ndisc_grace_source;
+
/* Generic DHCP stuff */
char *dhcp_anycast_address;
@@ -505,65 +530,16 @@ typedef struct _NMDevicePrivate {
NMProxyConfig * proxy_config;
NMPacrunnerConfId *pacrunner_conf_id;
- /* IP configuration info. Combined config from VPN, settings, and device */
union {
struct {
- NMIP6Config *ip_config_6;
- NMIP4Config *ip_config_4;
+ NMIPConfig *ip_config_6;
+ NMIPConfig *ip_config_4;
};
NMIPConfig *ip_config_x[2];
};
- /* Config from DHCP, PPP, LLv4, etc */
- AppliedConfig dev_ip_config_4;
-
- /* config from the setting */
- union {
- struct {
- NMIP6Config *con_ip_config_6;
- NMIP4Config *con_ip_config_4;
- };
- NMIPConfig *con_ip_config_x[2];
- };
-
- /* Stuff added outside NM */
- union {
- struct {
- NMIP6Config *ext_ip_config_6;
- NMIP4Config *ext_ip_config_4;
- };
- NMIPConfig *ext_ip_config_x[2];
- };
-
- /* VPNs which use this device */
- union {
- struct {
- GSList *vpn_configs_6;
- GSList *vpn_configs_4;
- };
- GSList *vpn_configs_x[2];
- };
-
- /* Extra device configuration, injected by the subclass of NMDevice.
- * This is used for example by NMDeviceModem for WWAN configuration. */
- union {
- struct {
- AppliedConfig dev2_ip_config_6;
- AppliedConfig dev2_ip_config_4;
- };
- AppliedConfig dev2_ip_config_x[2];
- };
-
- /* DHCPv4 tracking */
struct {
- char *pac_url;
- } dhcp4;
-
- struct {
- /* IP6 config from DHCP */
- AppliedConfig ip6_config;
/* Event ID of the current IP6 config from DHCP */
- char * event_id;
gulong prefix_sigid;
NMNDiscDHCPLevel mode;
guint needed_prefixes;
@@ -588,24 +564,17 @@ typedef struct _NMDevicePrivate {
} gw_ping;
/* dnsmasq stuff for shared connections */
- NMDnsMasqManager *dnsmasq_manager;
- gulong dnsmasq_state_id;
+ NMDnsMasqManager *shared4_dnsmasq_manager;
+ gulong shared4_dnsmasq_state_id;
/* Firewall */
FirewallState fw_state : 4;
NMFirewallManager * fw_mgr;
NMFirewallManagerCallId *fw_call;
- /* IPv4LL stuff */
- sd_ipv4ll *ipv4ll;
- guint ipv4ll_timeout;
- guint rt6_temporary_not_available_id;
-
- /* IPv4 DAD stuff */
- struct {
- GSList * dad_list;
- NMAcdManager *announcing;
- } acd;
+ NML3IPv4LL * ll4_ipv4ll;
+ NML3IPv4LLRegistration *ll4_ipv4ll_registation;
+ guint ll4_timeout_id;
union {
struct {
@@ -618,17 +587,12 @@ typedef struct _NMDevicePrivate {
};
};
- AppliedConfig ac_ip6_config; /* config from IPv6 autoconfiguration */
- NMIP6Config * ext_ip6_config_captured; /* Configuration captured from platform. */
- NMIP6Config * dad6_ip6_config;
struct in6_addr ipv6ll_addr;
- GHashTable *rt6_temporary_not_available;
-
- NMNDisc * ndisc;
- gulong ndisc_changed_id;
- gulong ndisc_timeout_id;
- NMSettingIP6ConfigPrivacy ndisc_use_tempaddr;
+ NMNDisc * ac6_ndisc;
+ gulong ac6_ndisc_changed_id;
+ gulong ac6_ndisc_timeout_id;
+ NMSettingIP6ConfigPrivacy ac6_ip6_privacy;
guint linklocal6_timeout_id;
guint8 linklocal6_dad_counter;
@@ -703,27 +667,23 @@ G_DEFINE_ABSTRACT_TYPE(NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
/*****************************************************************************/
+static NMSettingConnectionMdns _prop_get_connection_mdns(NMDevice *self);
+static NMSettingConnectionLlmnr _prop_get_connection_llmnr(NMDevice *self);
+
static const NMDBusInterfaceInfoExtended interface_info_device;
static const GDBusSignalInfo signal_info_state_changed;
-static void nm_device_set_proxy_config(NMDevice *self, const char *pac_url);
-
-static gboolean update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs);
+static void nm_device_set_proxy_config(NMDevice *self);
-static gboolean nm_device_set_ip_config(NMDevice * self,
- int addr_family,
- NMIPConfig *config,
- gboolean commit,
- GPtrArray * ip4_dev_route_blacklist);
+static void _dev_l3_cfg_commit(NMDevice *self);
-static gboolean ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit);
+static void _dev_l3_cfg_commit_type_reset(NMDevice *self);
static gboolean nm_device_master_add_slave(NMDevice *self, NMDevice *slave, gboolean configure);
static void nm_device_slave_notify_enslave(NMDevice *self, gboolean success);
static void nm_device_slave_notify_release(NMDevice *self, NMDeviceStateReason reason);
-static void addrconf6_start_with_link_ready(NMDevice *self);
-static gboolean linklocal6_start(NMDevice *self);
+static gboolean _dev_ll6_start(NMDevice *self, struct in6_addr *out_ll_addr);
static guint32 default_route_metric_penalty_get(NMDevice *self, int addr_family);
@@ -734,28 +694,36 @@ static NMIP6Config *dad6_get_pending_addresses(NMDevice *self);
static void _carrier_wait_check_queued_act_request(NMDevice *self);
static gint64 _get_carrier_wait_ms(NMDevice *self);
+static GBytes *_prop_get_ipv6_dhcp_duid(NMDevice * self,
+ NMConnection *connection,
+ GBytes * hwaddr,
+ gboolean * out_enforce);
+
static const char *_activation_func_to_string(ActivationHandleFunc func);
static void
_set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting);
-static void queued_state_clear(NMDevice *device);
-static gboolean queued_ip4_config_change(gpointer user_data);
-static gboolean queued_ip6_config_change(gpointer user_data);
-static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data);
-static gboolean ip_config_valid(NMDeviceState state);
-static NMActStageReturn dhcp4_start(NMDevice *self);
-static gboolean dhcp6_start(NMDevice *self, gboolean wait_for_ll);
-static void nm_device_start_ip_check(NMDevice *self);
-static void realize_start_setup(NMDevice * self,
- const NMPlatformLink *plink,
- gboolean assume_state_guess_assume,
- const char * assume_state_connection_uuid,
- gboolean set_nm_owned,
- NMUnmanFlagOp unmanaged_user_explicit,
- gboolean force_platform_init);
-static void _set_mtu(NMDevice *self, guint32 mtu);
-static void _commit_mtu(NMDevice *self, const NMIP4Config *config);
-static void _cancel_activation(NMDevice *self);
+static void queued_state_clear(NMDevice *device);
+static void ip_check_ping_watch_cb(GPid pid, int status, gpointer user_data);
+static void nm_device_start_ip_check(NMDevice *self);
+static void realize_start_setup(NMDevice * self,
+ const NMPlatformLink *plink,
+ gboolean assume_state_guess_assume,
+ const char * assume_state_connection_uuid,
+ gboolean set_nm_owned,
+ NMUnmanFlagOp unmanaged_user_explicit,
+ gboolean force_platform_init);
+static void _set_mtu(NMDevice *self, guint32 mtu);
+static void _commit_mtu(NMDevice *self);
+static void _cancel_activation(NMDevice *self);
+
+static void _dev_ll4_notify_event(NMDevice *self);
+
+static gboolean _dev_ac6_start(NMDevice *self);
+
+static void _dev_set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged);
+
+static gboolean _dev_shared4_start(NMDevice *self, GError **error);
static void concheck_update_state(NMDevice * self,
int addr_family,
@@ -765,7 +733,7 @@ static void concheck_update_state(NMDevice * self,
static void sriov_op_cb(GError *error, gpointer user_data);
static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self);
-static gboolean device_link_changed(NMDevice *self);
+static gboolean device_link_changed(gpointer user_data);
/*****************************************************************************/
@@ -1459,8 +1427,8 @@ _prop_get_ipvx_dhcp_timeout(NMDevice *self, int addr_family)
{
NMDeviceClass *klass;
NMConnection * connection;
- int timeout_i;
guint32 timeout;
+ int timeout_i;
nm_assert(NM_IS_DEVICE(self));
nm_assert_addr_family(addr_family);
@@ -2391,27 +2359,6 @@ concheck_get_mgr(NMDevice *self)
return priv->concheck_mgr;
}
-NMIP4Config *
-nm_device_ip4_config_new(NMDevice *self)
-{
- return nm_ip4_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self));
-}
-
-NMIP6Config *
-nm_device_ip6_config_new(NMDevice *self)
-{
- return nm_ip6_config_new(nm_device_get_multi_index(self), nm_device_get_ip_ifindex(self));
-}
-
-NMIPConfig *
-nm_device_ip_config_new(NMDevice *self, int addr_family)
-{
- nm_assert_addr_family(addr_family);
-
- return NM_IS_IPv4(addr_family) ? (gpointer) nm_device_ip4_config_new(self)
- : (gpointer) nm_device_ip6_config_new(self);
-}
-
NML3ConfigData *
nm_device_create_l3_config_data(NMDevice *self)
{
@@ -2426,98 +2373,33 @@ nm_device_create_l3_config_data(NMDevice *self)
return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex);
}
-static void
-applied_config_clear(AppliedConfig *config)
+static const NML3ConfigData *
+_dev_create_l3_config_data_from_connection(NMDevice *self, NMConnection *connection)
{
- g_clear_object(&config->current);
- g_clear_object(&config->orig);
-}
+ NML3ConfigData *l3cd;
+ int ifindex;
-static void
-applied_config_init(AppliedConfig *config, gpointer ip_config)
-{
- nm_assert(!ip_config || (!config->orig && !config->current)
- || nm_ip_config_get_addr_family(ip_config)
- == nm_ip_config_get_addr_family(config->orig ?: config->current));
- nm_assert(!ip_config || NM_IS_IP_CONFIG(ip_config));
-
- nm_g_object_ref(ip_config);
- applied_config_clear(config);
- config->orig = ip_config;
-}
-
-static void
-applied_config_init_new(AppliedConfig *config, NMDevice *self, int addr_family)
-{
- gs_unref_object NMIPConfig *c = nm_device_ip_config_new(self, addr_family);
-
- applied_config_init(config, c);
-}
-
-static NMIPConfig *
-applied_config_get_current(AppliedConfig *config)
-{
- return config->current ?: config->orig;
-}
-
-static void
-applied_config_add_address(AppliedConfig *config, const NMPlatformIPAddress *address)
-{
- if (config->orig)
- nm_ip_config_add_address(config->orig, address);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_address(config->current, address);
-}
-
-static void
-applied_config_add_nameserver(AppliedConfig *config, const NMIPAddr *ns)
-{
- if (config->orig)
- nm_ip_config_add_nameserver(config->orig, ns);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_nameserver(config->current, ns);
-}
-
-static void
-applied_config_add_search(AppliedConfig *config, const char *new)
-{
- if (config->orig)
- nm_ip_config_add_search(config->orig, new);
- else
- nm_assert(!config->current);
-
- if (config->current)
- nm_ip_config_add_search(config->current, new);
-}
-
-static void
-applied_config_reset_searches(AppliedConfig *config)
-{
- if (config->orig)
- nm_ip_config_reset_searches(config->orig);
- else
- nm_assert(!config->current);
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(!connection || NM_IS_CONNECTION(self));
- if (config->current)
- nm_ip_config_reset_searches(config->current);
-}
+ if (!connection)
+ return NULL;
-static void
-applied_config_reset_nameservers(AppliedConfig *config)
-{
- if (config->orig)
- nm_ip_config_reset_nameservers(config->orig);
- else
- nm_assert(!config->current);
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex <= 0)
+ g_return_val_if_reached(NULL);
- if (config->current)
- nm_ip_config_reset_nameservers(config->current);
+ l3cd = nm_l3_config_data_new_from_connection(nm_device_get_multi_index(self),
+ ifindex,
+ connection,
+ nm_device_get_route_table(self, AF_INET),
+ nm_device_get_route_table(self, AF_INET6),
+ nm_device_get_route_metric(self, AF_INET),
+ nm_device_get_route_metric(self, AF_INET6));
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_USER);
+ nm_l3_config_data_set_mdns(l3cd, _prop_get_connection_mdns(self));
+ nm_l3_config_data_set_llmnr(l3cd, _prop_get_connection_llmnr(self));
+ return nm_l3_config_data_seal(l3cd);
}
/*****************************************************************************/
@@ -2572,6 +2454,7 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st
_sys_iface_state_to_str(priv->sys_iface_state),
_sys_iface_state_to_str(sys_iface_state));
priv->sys_iface_state_ = sys_iface_state;
+ _dev_l3_cfg_commit_type_reset(self);
}
/* this function only sets a flag, no immediate actions are initiated.
@@ -2684,33 +2567,6 @@ nm_device_assume_state_reset(NMDevice *self)
/*****************************************************************************/
-static void
-init_ip_config_dns_priority(NMDevice *self, NMIPConfig *config)
-{
- const char *property;
- int priority;
-
- property = (nm_ip_config_get_addr_family(config) == AF_INET)
- ? NM_CON_DEFAULT("ipv4.dns-priority")
- : NM_CON_DEFAULT("ipv6.dns-priority");
-
- priority = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
- property,
- self,
- G_MININT,
- G_MAXINT,
- 0);
-
- if (priority == 0) {
- priority =
- nm_device_is_vpn(self) ? NM_DNS_PRIORITY_DEFAULT_VPN : NM_DNS_PRIORITY_DEFAULT_NORMAL;
- }
-
- nm_ip_config_set_dns_priority(config, priority);
-}
-
-/*****************************************************************************/
-
static char *
nm_device_sysctl_ip_conf_get(NMDevice *self, int addr_family, const char *property)
{
@@ -2887,6 +2743,427 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state)
}
}
+static void
+_set_ip_state_check(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
+
+ if (addr_family == AF_UNSPEC) {
+ _set_ip_state_check(self, AF_INET);
+ _set_ip_state_check(self, AF_INET6);
+ return;
+ }
+
+ nm_assert_addr_family(addr_family);
+
+ if (IS_IPv4) {
+ AddrMethodState addr_method_state_dhcp_4 = ADDR_METHOD_STATE_DISABLED;
+
+ if (priv->dhcp_data_4.client) {
+ /* DHCP is enabled. */
+ if (priv->dhcp_data_4.grace_pending) {
+ /* we are still waiting for DHCP to complete/succeed. */
+ addr_method_state_dhcp_4 = ADDR_METHOD_STATE_PENDING;
+ } else if (priv->dhcp_data_4.is_bad || !priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d) {
+ /* the DHCP configuration is failed. */
+ addr_method_state_dhcp_4 = ADDR_METHOD_STATE_FAILED;
+ } else
+ addr_method_state_dhcp_4 = ADDR_METHOD_STATE_GOOD;
+ }
+
+ (void) addr_method_state_dhcp_4;
+ }
+
+ // FIXME(l3cfg): need to check the current state and derive an overall _set_ip_state() value.
+
+ // FIXME(l3cfg): check for IPv6 addresses in DAD with nm_l3cfg_has_commited_ip6_addresses_pending_dad().
+}
+
+/*****************************************************************************/
+
+static L3ConfigDataType
+_dev_l3_config_data_tag_to_type(NMDevice *self, gconstpointer tag)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int d;
+
+ /* In C it is undefined behavior to compare unrelated pointers.
+ * Work around that by using nm_ptr_to_uintptr(), which casts the pointers
+ * to integers.
+ *
+ * I guess, theoretically it's still a problem to assume that if tag pointers
+ * somewhere inside priv->l3cds, that the uintptr_t case would also yield
+ * a value in that range. In practice, I couldn't imaging this not not work
+ * reliably. */
+
+ if (nm_ptr_to_uintptr(tag) < nm_ptr_to_uintptr(&priv->l3cds[0].d)
+ || nm_ptr_to_uintptr(tag) >= nm_ptr_to_uintptr(&priv->l3cds[G_N_ELEMENTS(priv->l3cds)].d))
+ return _L3_CONFIG_DATA_TYPE_NONE;
+
+ d = ((const NML3ConfigData **) tag) - (&priv->l3cds[0].d);
+
+ nm_assert(d >= 0);
+ nm_assert(d < _L3_CONFIG_DATA_TYPE_NUM);
+ nm_assert(tag == &priv->l3cds[d].d);
+ return d;
+}
+
+static void
+_dev_l3_get_config_settings(NMDevice * self,
+ L3ConfigDataType type,
+ NML3ConfigMergeFlags *out_merge_flags,
+ NML3AcdDefendType * out_acd_defend_type,
+ guint32 * out_acd_timeout_msec)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3ConfigMergeFlags flags;
+ NMConnection * connection;
+ NMSettingIPConfig * s_ip;
+
+ nm_assert(type >= 0 && type < _L3_CONFIG_DATA_TYPE_NUM);
+
+ if (G_UNLIKELY(!priv->l3config_merge_flags_has)) {
+ int IS_IPv4;
+
+ connection = nm_device_get_applied_connection(self);
+
+ for (IS_IPv4 = 0; IS_IPv4 < 2; IS_IPv4++) {
+ flags = NM_L3_CONFIG_MERGE_FLAGS_NONE;
+
+ if (connection
+ && (s_ip = nm_connection_get_setting_ip_config(connection,
+ IS_IPv4 ? AF_INET : AF_INET6))) {
+ if (nm_setting_ip_config_get_ignore_auto_routes(s_ip))
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES;
+
+ if (nm_setting_ip_config_get_ignore_auto_dns(s_ip))
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DNS;
+
+ if (nm_setting_ip_config_get_never_default(s_ip)
+ || nm_setting_ip_config_get_gateway(s_ip)) {
+ /* if the connection has an explicit gateway, we also ignore
+ * the default routes from other sources. */
+ flags |= NM_L3_CONFIG_MERGE_FLAGS_NO_DEFAULT_ROUTES;
+ }
+ }
+
+ priv->l3config_merge_flags_x[IS_IPv4] = flags;
+ }
+ priv->l3config_merge_flags_has = TRUE;
+ }
+
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_SETTING:
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ case L3_CONFIG_DATA_TYPE_DEV_4:
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEV_6:
+ *out_acd_timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ break;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ *out_acd_timeout_msec = nm_assert_unreachable_val(0);
+ break;
+ }
+
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ONCE;
+ break;
+
+ case L3_CONFIG_DATA_TYPE_SETTING:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ case L3_CONFIG_DATA_TYPE_DEV_4:
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEV_6:
+ *out_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_ALWAYS;
+ break;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ *out_acd_defend_type = nm_assert_unreachable_val(NM_L3_ACD_DEFEND_TYPE_ALWAYS);
+ break;
+ }
+
+ switch (type) {
+ case L3_CONFIG_DATA_TYPE_SETTING:
+ case L3_CONFIG_DATA_TYPE_LL_4:
+ case L3_CONFIG_DATA_TYPE_LL_6:
+ case L3_CONFIG_DATA_TYPE_PD_6:
+ case L3_CONFIG_DATA_TYPE_SHARED_4:
+ *out_merge_flags = NM_L3_CONFIG_MERGE_FLAGS_NONE;
+ break;
+
+ case L3_CONFIG_DATA_TYPE_DHCP_4:
+ case L3_CONFIG_DATA_TYPE_DEV_4:
+ *out_merge_flags = priv->l3config_merge_flags_4;
+ break;
+
+ case L3_CONFIG_DATA_TYPE_AC_6:
+ case L3_CONFIG_DATA_TYPE_DHCP_6:
+ case L3_CONFIG_DATA_TYPE_DEV_6:
+ *out_merge_flags = priv->l3config_merge_flags_6;
+ break;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ *out_merge_flags = nm_assert_unreachable_val(NM_L3_CONFIG_MERGE_FLAGS_NONE);
+ break;
+ }
+}
+
+static gboolean
+_dev_l3_register_l3cds_add_config(NMDevice *self, L3ConfigDataType l3cd_type)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3ConfigMergeFlags merge_flags;
+ NML3AcdDefendType acd_defend_type;
+ guint32 acd_timeout_msec;
+
+ _dev_l3_get_config_settings(self, l3cd_type, &merge_flags, &acd_defend_type, &acd_timeout_msec);
+ return nm_l3cfg_add_config(priv->l3cfg,
+ &priv->l3cds[l3cd_type].d,
+ FALSE,
+ priv->l3cds[l3cd_type].d,
+ l3cd_type,
+ nm_device_get_route_table(self, AF_INET),
+ nm_device_get_route_table(self, AF_INET6),
+ nm_device_get_route_metric(self, AF_INET),
+ nm_device_get_route_metric(self, AF_INET6),
+ default_route_metric_penalty_get(self, AF_INET),
+ default_route_metric_penalty_get(self, AF_INET6),
+ acd_defend_type,
+ acd_timeout_msec,
+ merge_flags);
+}
+
+static gboolean
+_dev_l3_register_l3cds_set_one(NMDevice * self,
+ L3ConfigDataType l3cd_type,
+ const NML3ConfigData *l3cd)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old_free = NULL;
+ const NML3ConfigData * l3cd_old;
+ gboolean changed = FALSE;
+
+ l3cd_old = priv->l3cds[l3cd_type].d;
+ if (l3cd != priv->l3cds[l3cd_type].d) {
+ l3cd_old_free = g_steal_pointer(&priv->l3cds[l3cd_type].d);
+ if (l3cd)
+ priv->l3cds[l3cd_type].d = nm_l3_config_data_ref_and_seal(l3cd);
+ }
+
+ if (priv->l3cfg) {
+ if (_dev_l3_register_l3cds_add_config(self, l3cd_type))
+ changed = TRUE;
+
+ if (l3cd_old && l3cd_old != l3cd) {
+ if (nm_l3cfg_remove_config(priv->l3cfg, &priv->l3cds[l3cd_type].d, l3cd_old))
+ changed = TRUE;
+ }
+ }
+
+ return changed;
+}
+
+static gboolean
+_dev_l3_register_l3cds(NMDevice *self,
+ NML3Cfg * l3cfg,
+ gboolean do_add /* else remove */,
+ NMTernary do_commit)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gboolean is_external;
+ gboolean changed;
+ int i;
+
+ if (!l3cfg)
+ return FALSE;
+
+ is_external = nm_device_sys_iface_state_is_external(self);
+
+ changed = FALSE;
+ for (i = 0; i < G_N_ELEMENTS(priv->l3cds); i++) {
+ if (!priv->l3cds[i].d)
+ continue;
+ if (!do_add) {
+ if (nm_l3cfg_remove_config(l3cfg, &priv->l3cds[i].d, priv->l3cds[i].d))
+ changed = TRUE;
+ continue;
+ }
+ if (is_external)
+ continue;
+ if (_dev_l3_register_l3cds_add_config(self, i))
+ changed = TRUE;
+ }
+
+ if (do_commit == NM_TERNARY_DEFAULT)
+ do_commit = changed;
+ if (do_commit)
+ _dev_l3_cfg_commit(self);
+
+ return changed;
+}
+
+static void
+_dev_l3_notify_change(NMDevice *self, int addr_family)
+{
+ /* FIXME(l3cfg) */
+ nm_device_activate_schedule_ip_config_result(self, addr_family);
+}
+
+static void
+_dev_l3_cfg_commit(NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ if (priv->l3cfg)
+ nm_l3cfg_commit(priv->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO);
+}
+
+static void
+_dev_l3_cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ nm_assert(l3cfg == priv->l3cfg);
+
+ /* FIXME(l3cfg) */
+ switch (notify_data->notify_type) {
+ case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT:
+ {
+ const NML3AcdAddrInfo *addr_info = &notify_data->acd_event.info;
+ guint i;
+
+ for (i = 0; i < addr_info->n_track_infos; i++) {
+ L3ConfigDataType l3cd_type =
+ _dev_l3_config_data_tag_to_type(self, addr_info->track_infos[i].tag);
+
+ if (NM_IN_SET(l3cd_type, L3_CONFIG_DATA_TYPE_DHCP_4)) {
+ nm_dhcp_client_decline(priv->dhcp_data_4.client, "Address conflict detected", NULL);
+ nm_device_ip_method_failed(self,
+ AF_INET,
+ NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
+ return;
+ }
+ }
+ _dev_l3_notify_change(self, AF_INET);
+ return;
+ }
+ case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT:
+ /* FIXME(l3cfg) */
+ _dev_l3_notify_change(self, AF_INET);
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT:
+ if (priv->ll4_ipv4ll == notify_data->ipv4ll_event.ipv4ll)
+ _dev_ll4_notify_event(self);
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE:
+ case NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED:
+ /* FIXME(l3cfg) */
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE:
+ if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags,
+ nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ADDRESS)
+ | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ROUTE)))
+ _dev_l3_notify_change(self, AF_INET);
+ if (NM_FLAGS_ANY(notify_data->platform_change_on_idle.obj_type_flags,
+ nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ADDRESS)
+ | nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP6_ROUTE)))
+ _dev_l3_notify_change(self, AF_INET6);
+
+ _dev_set_unmanaged_external_down(self, TRUE);
+ return;
+ case _NM_L3_CONFIG_NOTIFY_TYPE_NUM:
+ break;
+ }
+ nm_assert_not_reached();
+}
+
+static void
+_dev_l3_cfg_commit_type_reset(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3CfgCommitType commit_type;
+
+ if (!priv->l3cfg)
+ return;
+
+ switch (priv->sys_iface_state) {
+ case NM_DEVICE_SYS_IFACE_STATE_EXTERNAL:
+ case NM_DEVICE_SYS_IFACE_STATE_REMOVED:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_NONE;
+ goto do_set;
+ case NM_DEVICE_SYS_IFACE_STATE_ASSUME:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_ASSUME;
+ goto do_set;
+ case NM_DEVICE_SYS_IFACE_STATE_MANAGED:
+ commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE;
+ goto do_set;
+ }
+ nm_assert_not_reached();
+ return;
+
+do_set:
+ priv->l3cfg_commit_type =
+ nm_l3cfg_commit_type_register(priv->l3cfg, commit_type, priv->l3cfg_commit_type);
+}
+
+/*****************************************************************************/
+
+//XXX FIXME(l3cfg)
+_nm_unused static gboolean
+_dev_l3_set_l3cd_setting(NMDevice *self)
+{
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+
+ l3cd = _dev_create_l3_config_data_from_connection(self, nm_device_get_applied_connection(self));
+ return _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SETTING, l3cd);
+}
+
+static gboolean
+_dev_l3_set_l3cd_ll_6(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+
+ if (priv->ipv6ll_has) {
+ const NMPlatformIP6Address ll_a = {
+ .address = priv->ipv6ll_addr,
+ .plen = 64,
+ .addr_source = NM_IP_CONFIG_SOURCE_IP6LL,
+ };
+ const NMPlatformIP6Route ll_r = {
+ .network.s6_addr16[0] = htons(0xfe80u),
+ .plen = 64,
+ .metric = nm_device_get_route_metric(self, AF_INET6),
+ .rt_source = NM_IP_CONFIG_SOURCE_IP6LL,
+ };
+
+ nm_assert(IN6_IS_ADDR_LINKLOCAL(&priv->ipv6ll_addr));
+
+ l3cd = nm_device_create_l3_config_data(self);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_IP6LL);
+ nm_l3_config_data_add_address_6(l3cd, &ll_a);
+ nm_l3_config_data_add_route_6(l3cd, &ll_r);
+ nm_l3_config_data_seal(l3cd);
+ }
+
+ return _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_6, l3cd);
+}
+
/*****************************************************************************/
const char *
@@ -2908,8 +3185,13 @@ nm_device_get_iface(NMDevice *self)
static gboolean
_set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- int * p_ifindex;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gs_unref_object NML3Cfg *l3cfg_old = NULL;
+ NML3CfgCommitTypeHandle *l3cfg_commit_type_old = NULL;
+ gboolean l3_changed;
+ int ip_ifindex_new;
+ int * p_ifindex;
+ gboolean l3cfg_was_reset = FALSE;
if (ifindex < 0)
ifindex = 0;
@@ -2921,13 +3203,78 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex)
*p_ifindex = ifindex;
- _LOGD(LOGD_DEVICE, "ifindex: set %sifindex %d", is_ip_ifindex ? "ip-" : "", ifindex);
+ ip_ifindex_new = nm_device_get_ip_ifindex(self);
- if (!is_ip_ifindex)
- _notify(self, PROP_IFINDEX);
+ if (priv->l3cfg) {
+ if (ip_ifindex_new <= 0 || ip_ifindex_new != nm_l3cfg_get_ifindex(priv->l3cfg)) {
+ g_signal_handlers_disconnect_by_func(priv->l3cfg,
+ G_CALLBACK(_dev_l3_cfg_notify_cb),
+ self);
+ l3cfg_old = g_steal_pointer(&priv->l3cfg_);
+ l3cfg_commit_type_old = g_steal_pointer(&priv->l3cfg_commit_type);
+ l3cfg_was_reset = TRUE;
+ }
+ }
+ if (!priv->l3cfg && ip_ifindex_new > 0) {
+ priv->l3cfg_ = nm_netns_access_l3cfg(priv->netns, ip_ifindex_new);
+
+ g_signal_connect(priv->l3cfg,
+ NM_L3CFG_SIGNAL_NOTIFY,
+ G_CALLBACK(_dev_l3_cfg_notify_cb),
+ self);
+
+ _dev_l3_cfg_commit_type_reset(self);
+ l3cfg_was_reset = TRUE;
+ }
+
+ _LOGD(LOGD_DEVICE,
+ "ifindex: set %sifindex %d%s%s%s%s%s%s",
+ is_ip_ifindex ? "ip-" : "",
+ ifindex,
+ NM_PRINT_FMT_QUOTED(l3cfg_old && l3cfg_old != priv->l3cfg,
+ " (old-l3cfg: ",
+ nm_hash_obfuscated_ptr_str_a(l3cfg_old),
+ ")",
+ ""),
+ NM_PRINT_FMT_QUOTED(priv->l3cfg && l3cfg_old != priv->l3cfg,
+ " (l3cfg: ",
+ nm_hash_obfuscated_ptr_str_a(priv->l3cfg),
+ ")",
+ ""));
if (priv->manager)
nm_manager_emit_device_ifindex_changed(priv->manager, self);
+
+ if (!is_ip_ifindex)
+ _notify(self, PROP_IFINDEX);
+
+ if (l3cfg_was_reset) {
+ nm_dbus_object_unexport_on_idle(g_steal_pointer(&priv->ip_config_4));
+ nm_dbus_object_unexport_on_idle(g_steal_pointer(&priv->ip_config_6));
+
+ if (priv->l3cfg) {
+ priv->ip_config_4 = nm_ip_config_new(AF_INET, priv->l3cfg, FALSE);
+ priv->ip_config_6 = nm_ip_config_new(AF_INET6, priv->l3cfg, FALSE);
+ nm_dbus_object_export(priv->ip_config_4);
+ nm_dbus_object_export(priv->ip_config_6);
+ }
+
+ _notify(self, PROP_IP4_CONFIG);
+ _notify(self, PROP_IP6_CONFIG);
+ }
+
+ l3_changed = FALSE;
+ if (_dev_l3_register_l3cds(self, priv->l3cfg, TRUE, FALSE))
+ l3_changed = TRUE;
+ if (_dev_l3_register_l3cds(self, l3cfg_old, FALSE, FALSE))
+ l3_changed = TRUE;
+
+ if (l3_changed)
+ _dev_l3_cfg_commit(self);
+
+ if (l3cfg_commit_type_old)
+ nm_l3cfg_commit_type_unregister(l3cfg_old, l3cfg_commit_type_old);
+
return TRUE;
}
@@ -3663,7 +4010,8 @@ nm_device_get_route_metric_default(NMDeviceType device_type)
return 11000;
}
-static gboolean
+//XXX FIXME(l3cfg)
+_nm_unused static gboolean
default_route_metric_penalty_detect(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -3747,28 +4095,22 @@ nm_device_get_route_table(NMDevice *self, int addr_family)
return route_table ?: (guint32) RT_TABLE_MAIN;
}
-static NMIPRouteTableSyncMode
+//XXX
+_nm_unused static NMIPRouteTableSyncMode
_get_route_table_sync_mode_stateful(NMDevice *self, int addr_family)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMDedupMultiIter ipconf_iter;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
gboolean all_sync_now;
gboolean all_sync_eff;
all_sync_now = _prop_get_ipvx_route_table(self, addr_family) != 0u;
if (!all_sync_now) {
- const NMPlatformIPRoute *route;
+ const NML3ConfigData *l3cd = priv->l3cds[L3_CONFIG_DATA_TYPE_SETTING].d;
/* If there's a local route switch to all-sync in order
* to properly manage the local table */
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, priv->con_ip_config_x[IS_IPv4], &route) {
- if (nm_platform_route_type_uncoerce(route->type_coerced) == RTN_LOCAL) {
- all_sync_now = TRUE;
- break;
- }
- }
+ all_sync_now = l3cd && nm_l3_config_data_has_routes_with_type_local(l3cd, addr_family);
}
if (all_sync_now)
@@ -3800,18 +4142,10 @@ nm_device_get_best_default_route(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- switch (addr_family) {
- case AF_INET:
- return priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL;
- case AF_INET6:
- return priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6) : NULL;
- case AF_UNSPEC:
- return (priv->ip_config_4 ? nm_ip4_config_best_default_route_get(priv->ip_config_4) : NULL)
- ?: (priv->ip_config_6 ? nm_ip6_config_best_default_route_get(priv->ip_config_6)
- : NULL);
- default:
- g_return_val_if_reached(NULL);
- }
+ if (!priv->l3cfg)
+ return NULL;
+
+ return nm_l3cfg_get_best_default_route(priv->l3cfg, addr_family, TRUE);
}
const char *
@@ -4366,14 +4700,8 @@ concheck_update_state(NMDevice * self,
_notify(self, IS_IPv4 ? PROP_IP4_CONNECTIVITY : PROP_IP6_CONNECTIVITY);
- if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self)) {
- if (nm_device_get_best_default_route(self, AF_INET)
- && !ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "Failed to update IPv4 route metric");
- if (nm_device_get_best_default_route(self, AF_INET6)
- && !ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "Failed to update IPv6 route metric");
- }
+ if (priv->state == NM_DEVICE_STATE_ACTIVATED && !nm_device_sys_iface_state_is_external(self))
+ _dev_l3_register_l3cds(self, priv->l3cfg, AF_UNSPEC, NM_TERNARY_DEFAULT);
}
static const char *
@@ -4740,10 +5068,6 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co
*/
nm_device_update_hw_address(self);
- /* Send ARP announcements if did not yet and have addresses. */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing)
- nm_device_arp_announce(self);
-
/* Restart IP configuration if we're waiting for slaves. Do this
* after updating the hardware address as IP config may need the
* new address.
@@ -4759,7 +5083,7 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co
/* Since slave devices don't have their own IP configuration,
* set the MTU here.
*/
- _commit_mtu(slave, NM_DEVICE_GET_PRIVATE(slave)->ip_config_4);
+ _commit_mtu(slave);
return success;
}
@@ -4877,7 +5201,7 @@ is_unmanaged_external_down(NMDevice *self, gboolean consider_can)
}
static void
-set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged)
+_dev_set_unmanaged_external_down(NMDevice *self, gboolean only_if_unmanaged)
{
NMUnmanFlagOp ext_flags;
@@ -4918,7 +5242,7 @@ nm_device_update_dynamic_ip_setup(NMDevice *self)
g_hash_table_remove_all(priv->ip6_saved_properties);
if (priv->dhcp_data_4.client) {
- if (!nm_device_dhcp4_renew(self, FALSE)) {
+ if (!nm_device_dhcp_renew(self, AF_INET, FALSE)) {
nm_device_state_changed(self,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_DHCP_FAILED);
@@ -4926,17 +5250,17 @@ nm_device_update_dynamic_ip_setup(NMDevice *self)
}
}
if (priv->dhcp_data_6.client) {
- if (!nm_device_dhcp6_renew(self, FALSE)) {
+ if (!nm_device_dhcp_renew(self, AF_INET6, FALSE)) {
nm_device_state_changed(self,
NM_DEVICE_STATE_FAILED,
NM_DEVICE_STATE_REASON_DHCP_FAILED);
return;
}
}
- if (priv->ndisc) {
+ if (priv->ac6_ndisc) {
/* FIXME: todo */
}
- if (priv->dnsmasq_manager) {
+ if (priv->shared4_dnsmasq_manager) {
/* FIXME: todo */
}
}
@@ -5203,82 +5527,20 @@ device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice
}
static void
-ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self)
+_dev_ac6_ndisc_set_router_config(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_unref_array GArray *addresses = NULL;
- gs_unref_array GArray *dns_servers = NULL;
- gs_unref_array GArray * dns_domains = NULL;
- guint len;
- guint i;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter ipconf_iter;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd;
- if (nm_ndisc_get_node_type(ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
+ if (!priv->ac6_ndisc)
return;
- head_entry = nm_ip6_config_lookup_addresses(priv->ip_config_6);
- addresses =
- g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscAddress), head_entry ? head_entry->len : 0);
- nm_dedup_multi_iter_for_each (&ipconf_iter, head_entry) {
- const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter.current->obj);
- NMNDiscAddress * ndisc_addr;
- guint32 lifetime;
- guint32 preferred;
-
- if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address))
- continue;
-
- if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED)
- continue;
-
- if (addr->plen != 64)
- continue;
-
- lifetime = nmp_utils_lifetime_get(addr->timestamp,
- addr->lifetime,
- addr->preferred,
- NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
- &preferred);
- if (!lifetime)
- continue;
-
- g_array_set_size(addresses, addresses->len + 1);
- ndisc_addr = &g_array_index(addresses, NMNDiscAddress, addresses->len - 1);
- ndisc_addr->address = addr->address;
- ndisc_addr->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime);
- ndisc_addr->expiry_preferred_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred);
- }
-
- len = nm_ip6_config_get_num_nameservers(priv->ip_config_6);
- dns_servers = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSServer), len);
- g_array_set_size(dns_servers, len);
- for (i = 0; i < len; i++) {
- const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(priv->ip_config_6, i);
- NMNDiscDNSServer * ndisc_nameserver;
-
- ndisc_nameserver = &g_array_index(dns_servers, NMNDiscDNSServer, i);
- ndisc_nameserver->address = *nameserver;
- ndisc_nameserver->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
- }
-
- len = nm_ip6_config_get_num_searches(priv->ip_config_6);
- dns_domains = g_array_sized_new(FALSE, TRUE, sizeof(NMNDiscDNSDomain), len);
- g_array_set_size(dns_domains, len);
- for (i = 0; i < len; i++) {
- const char * search = nm_ip6_config_get_search(priv->ip_config_6, i);
- NMNDiscDNSDomain *ndisc_search;
-
- ndisc_search = &g_array_index(dns_domains, NMNDiscDNSDomain, i);
- ndisc_search->domain = (char *) search;
- ndisc_search->expiry_msec =
- _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, NM_NDISC_ROUTER_LIFETIME);
- }
+ if (nm_ndisc_get_node_type(priv->ac6_ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
+ return;
- nm_ndisc_set_config(ndisc, addresses, dns_servers, dns_domains);
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE);
+ if (l3cd)
+ nm_ndisc_set_config(priv->ac6_ndisc, l3cd);
}
static void
@@ -5312,8 +5574,9 @@ device_update_interface_flags(NMDevice *self, const NMPlatformLink *plink)
}
static gboolean
-device_link_changed(NMDevice *self)
+device_link_changed(gpointer user_data)
{
+ NMDevice * self = user_data;
NMDeviceClass * klass = NM_DEVICE_GET_CLASS(self);
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
gboolean ip_ifname_changed = FALSE;
@@ -5398,8 +5661,8 @@ device_link_changed(NMDevice *self)
nm_device_emit_recheck_auto_activate(self);
}
- if (priv->ndisc && pllink->inet6_token.id) {
- if (nm_ndisc_set_iid(priv->ndisc, pllink->inet6_token))
+ if (priv->ac6_ndisc && pllink->inet6_token.id) {
+ if (nm_ndisc_set_iid(priv->ac6_ndisc, pllink->inet6_token))
_LOGD(LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
}
@@ -5446,23 +5709,15 @@ device_link_changed(NMDevice *self)
nm_device_set_unmanaged_by_flags(self, NM_UNMANAGED_PLATFORM_INIT, FALSE, reason);
}
- set_unmanaged_external_down(self, FALSE);
+ _dev_set_unmanaged_external_down(self, FALSE);
device_recheck_slave_status(self, pllink);
if (priv->up && (!was_up || seen_down)) {
+ priv->linklocal6_dad_counter = 0;
/* the link was down and just came up. That happens for example, while changing MTU.
* We must restore IP configuration. */
- if (NM_IN_SET(priv->ip_state_4, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) {
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed applying IP4 config after link comes up again");
- }
-
- priv->linklocal6_dad_counter = 0;
- if (NM_IN_SET(priv->ip_state_6, NM_DEVICE_IP_STATE_CONF, NM_DEVICE_IP_STATE_DONE)) {
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed applying IP6 config after link comes up again");
- }
+ _dev_l3_cfg_commit(self);
}
if (update_unmanaged_specs)
@@ -5484,8 +5739,9 @@ device_link_changed(NMDevice *self)
}
static gboolean
-device_ip_link_changed(NMDevice *self)
+device_ip_link_changed(gpointer user_data)
{
+ NMDevice * self = user_data;
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
const NMPlatformLink *pllink;
const char * ip_iface;
@@ -5548,13 +5804,12 @@ link_changed_cb(NMPlatform * platform,
if (!(info->n_ifi_flags & IFF_UP))
priv->device_link_changed_down = TRUE;
if (!priv->device_link_changed_id) {
- priv->device_link_changed_id = g_idle_add((GSourceFunc) device_link_changed, self);
+ priv->device_link_changed_id = g_idle_add(device_link_changed, self);
_LOGD(LOGD_DEVICE, "queued link change for ifindex %d", ifindex);
}
} else if (ifindex == nm_device_get_ip_ifindex(self)) {
if (!priv->device_ip_link_changed_id) {
- priv->device_ip_link_changed_id =
- g_idle_add((GSourceFunc) device_ip_link_changed, self);
+ priv->device_ip_link_changed_id = g_idle_add(device_ip_link_changed, self);
_LOGD(LOGD_DEVICE, "queued link change for ip-ifindex %d", ifindex);
}
}
@@ -6002,8 +6257,6 @@ realize_start_setup(NMDevice * self,
g_return_if_fail(nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT));
g_return_if_fail(priv->ip_ifindex <= 0);
g_return_if_fail(priv->ip_iface == NULL);
- g_return_if_fail(!priv->queued_ip_config_id_4);
- g_return_if_fail(!priv->queued_ip_config_id_6);
_LOGD(LOGD_DEVICE,
"start setup of %s, kernel ifindex %d",
@@ -6147,9 +6400,6 @@ nm_device_realize_finish(NMDevice *self, const NMPlatformLink *plink)
if (plink)
device_recheck_slave_status(self, plink);
- priv->update_ip_config_completed_v4 = FALSE;
- priv->update_ip_config_completed_v6 = FALSE;
-
priv->real = TRUE;
_notify(self, PROP_REAL);
@@ -6245,9 +6495,6 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error)
}
}
- nm_clear_g_source(&priv->queued_ip_config_id_4);
- nm_clear_g_source(&priv->queued_ip_config_id_6);
-
g_object_freeze_notify(G_OBJECT(self));
NM_DEVICE_GET_CLASS(self)->unrealize_notify(self);
@@ -6839,15 +7086,12 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config)
NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED);
}
- if (unconfigure_ip_config) {
- nm_device_set_ip_config(self, AF_INET, NULL, FALSE, NULL);
- nm_device_set_ip_config(self, AF_INET6, NULL, FALSE, NULL);
- } else {
- if (priv->dhcp_data_4.client)
- nm_dhcp_client_stop(priv->dhcp_data_4.client, FALSE);
- if (priv->dhcp_data_6.client)
- nm_dhcp_client_stop(priv->dhcp_data_6.client, FALSE);
- }
+ if (priv->dhcp_data_4.client)
+ nm_dhcp_client_stop(priv->dhcp_data_4.client, FALSE);
+ if (priv->dhcp_data_6.client)
+ nm_dhcp_client_stop(priv->dhcp_data_6.client, FALSE);
+
+ _dev_l3_register_l3cds(self, priv->l3cfg, FALSE, TRUE);
}
static gboolean
@@ -7105,22 +7349,36 @@ nm_device_can_auto_connect(NMDevice *self, NMSettingsConnection *sett_conn, char
static gboolean
device_has_config(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const NMDedupMultiHeadEntry *head_entry;
+ const NMPlatformLink * pllink;
+ NMPLookup lookup;
- /* Check for IP configuration. */
- if (priv->ip_config_4 && nm_ip4_config_get_num_addresses(priv->ip_config_4))
+ pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE);
+ if (!pllink)
+ return FALSE;
+
+ if (pllink->master > 0) {
+ /* Master-slave relationship is also a configuration */
return TRUE;
- if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6))
+ }
+
+ head_entry = nm_platform_lookup(
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, pllink->ifindex));
+ if (head_entry)
return TRUE;
- /* The existence of a software device is good enough. */
- if (nm_device_is_software(self) && nm_device_is_real(self))
+ head_entry = nm_platform_lookup(
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, pllink->ifindex));
+ if (head_entry)
return TRUE;
- /* Master-slave relationship is also a configuration */
- if (!c_list_is_empty(&priv->slaves)
- || nm_platform_link_get_master(nm_device_get_platform(self), priv->ifindex) > 0)
+ if (nm_device_is_software(self) && nm_device_is_real(self)) {
+ /* The existence of a software device is good enough. */
return TRUE;
+ }
return FALSE;
}
@@ -7174,7 +7432,8 @@ nm_device_master_update_slave_connection(NMDevice * self,
return FALSE;
}
-static gboolean
+//XXX
+_nm_unused static gboolean
_get_maybe_ipv6_disabled(NMDevice *self)
{
NMPlatform *platform;
@@ -7268,11 +7527,13 @@ nm_device_generate_connection(NMDevice *self,
}
} else {
/* Only regular and master devices get IP configuration; slaves do not */
- s_ip4 = nm_ip4_config_create_setting(priv->ip_config_4);
- nm_connection_add_setting(connection, s_ip4);
+ //XXX s_ip4 = nm_ip4_config_create_setting (priv->ip_config_4);
+ //XXX nm_connection_add_setting (connection, s_ip4);
+ (void) s_ip4;
- s_ip6 = nm_ip6_config_create_setting(priv->ip_config_6, _get_maybe_ipv6_disabled(self));
- nm_connection_add_setting(connection, s_ip6);
+ //XXX s_ip6 = nm_ip6_config_create_setting (priv->ip_config_6, _get_maybe_ipv6_disabled (self));
+ //XXX nm_connection_add_setting (connection, s_ip6);
+ s_ip6 = NULL;
nm_connection_add_setting(connection, nm_setting_proxy_new());
@@ -7725,20 +7986,6 @@ nm_device_emit_recheck_auto_activate(NMDevice *self)
g_signal_emit(self, signals[RECHECK_AUTO_ACTIVATE], 0);
}
-static void
-dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint32 status, gpointer user_data)
-{
- NMDevice *self = NM_DEVICE(user_data);
-
- switch (status) {
- case NM_DNSMASQ_STATUS_DEAD:
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
- break;
- default:
- break;
- }
-}
-
void
nm_device_auth_request(NMDevice * self,
GDBusMethodInvocation * context,
@@ -8075,6 +8322,7 @@ activate_stage1_device_prepare(NMDevice *self)
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
_set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_NONE);
_set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_NONE);
@@ -8554,1126 +8802,983 @@ nm_device_ip_method_failed(NMDevice *self, int addr_family, NMDeviceStateReason
/*****************************************************************************/
static void
-acd_data_destroy(gpointer ptr)
+_dev_ll4_cleanup(NMDevice *self)
{
- AcdData *data = ptr;
- int i;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- for (i = 0; data->configs && data->configs[i]; i++)
- g_object_unref(data->configs[i]);
- g_free(data->configs);
- g_slice_free(AcdData, data);
-}
+ priv->ll4_ipv4ll_failed = FALSE;
+ priv->ll4_ipv4ll_ready = FALSE;
-static void
-ipv4_manual_method_apply(NMDevice *self, NMIP4Config **configs, gboolean success)
-{
- NMConnection *connection;
- const char * method;
-
- connection = nm_device_get_applied_connection(self);
- nm_assert(connection);
- method = nm_utils_get_ip_config_method(connection, AF_INET);
- nm_assert(NM_IN_STRSET(method,
- NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
- NM_SETTING_IP4_CONFIG_METHOD_AUTO));
+ if (nm_clear_pointer(&priv->ll4_ipv4ll, nm_l3_ipv4ll_unref))
+ nm_clear_pointer(&priv->ll4_ipv4ll_registation, nm_l3_ipv4ll_register_remove);
+ else
+ nm_assert(!priv->ll4_ipv4ll_registation);
- if (!success) {
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
- return;
- }
+ nm_clear_g_source(&priv->ll4_timeout_id);
- if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NULL);
- else {
- if (NM_DEVICE_GET_PRIVATE(self)->ip_state_4 != NM_DEVICE_IP_STATE_DONE)
- ip_config_merge_and_apply(self, AF_INET, TRUE);
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_4, NULL);
}
static void
-acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data)
+_dev_ll4_notify_event(NMDevice *self)
{
- AcdData * data = user_data;
- NMDevice * self;
- NMDevicePrivate * priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- gboolean result, success = TRUE;
- int i;
-
- g_assert(data);
- self = data->device;
- priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3IPv4LLState ipv4ll_state = NM_L3_IPV4LL_STATE_UNKNOWN;
+ const NML3ConfigData *l3cd;
- for (i = 0; data->configs && data->configs[i]; i++) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, data->configs[i], &address) {
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- result = nm_acd_manager_check_address(acd_manager, address->address);
- success &= result;
+ ipv4ll_state =
+ priv->ll4_ipv4ll ? nm_l3_ipv4ll_get_state(priv->ll4_ipv4ll) : NM_L3_IPV4LL_STATE_UNKNOWN;
- _NMLOG(result ? LOGL_DEBUG : LOGL_WARN,
- LOGD_DEVICE,
- "IPv4 DAD result: address %s is %s",
- _nm_utils_inet4_ntop(address->address, sbuf),
- result ? "unique" : "duplicate");
- }
+ if (nm_l3_ipv4ll_state_is_good(ipv4ll_state)) {
+ priv->ll4_ipv4ll_failed = FALSE;
+ priv->ll4_ipv4ll_ready = TRUE;
+ l3cd = nm_l3_ipv4ll_get_l3cd(priv->ll4_ipv4ll);
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert(!nm_l3_ipv4ll_is_timed_out(priv->ll4_ipv4ll));
+ } else {
+ priv->ll4_ipv4ll_failed = (priv->ll4_ipv4ll && nm_l3_ipv4ll_is_timed_out(priv->ll4_ipv4ll));
+ l3cd = NULL;
}
- data->callback(self, data->configs, success);
+ if (_dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_4, l3cd))
+ _dev_l3_cfg_commit(self);
- priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager);
- nm_acd_manager_free(acd_manager);
+ _set_ip_state_check(self, AF_INET);
}
-/**
- * ipv4_dad_start:
- * @self: device instance
- * @configs: NULL-terminated array of IPv4 configurations
- * @cb: callback function
- *
- * Start IPv4 DAD on device @self, check addresses in @configs and call @cb
- * when the procedure ends. @cb will be called in any case, even if DAD can't
- * be started. @configs will be unreferenced after @cb has been called.
- */
-static void
-ipv4_dad_start(NMDevice *self, NMIP4Config **configs, AcdCallback cb)
+static NMActStageReturn
+_dev_ll4_start(NMDevice *self)
{
- static const NMAcdCallbacks acd_callbacks = {
- .probe_terminated_callback = acd_manager_probe_terminated,
- .user_data_destroy = acd_data_destroy,
- };
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMAcdManager * acd_manager;
- const NMPlatformIP4Address *address;
- NMDedupMultiIter ipconf_iter;
- AcdData * data;
- guint timeout;
- gboolean addr_found;
- int r;
- const guint8 * hwaddr_arr;
- size_t length;
- guint i;
-
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(configs);
- g_return_if_fail(cb);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ guint timeout_msec;
- for (i = 0, addr_found = FALSE; configs[i]; i++) {
- if (nm_ip4_config_get_num_addresses(configs[i]) > 0) {
- addr_found = TRUE;
- break;
- }
- }
+ _dev_ll4_cleanup(self);
- timeout = _prop_get_ipv4_dad_timeout(self);
- hwaddr_arr = nm_platform_link_get_address(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- &length);
+ timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ if (timeout_msec == 0)
+ timeout_msec = NM_ACD_TIMEOUT_RFC5227_MSEC;
- if (!timeout || !hwaddr_arr || !addr_found || length != ETH_ALEN
- || nm_device_sys_iface_state_is_external_or_assume(self)) {
- /* DAD not needed, signal success */
- cb(self, configs, TRUE);
+ _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "ipv4ll: enabling");
- for (i = 0; configs[i]; i++)
- g_object_unref(configs[i]);
- g_free(configs);
+ priv->ll4_ipv4ll = nm_l3cfg_access_ipv4ll(priv->l3cfg);
+ priv->ll4_ipv4ll_registation = nm_l3_ipv4ll_register_new(priv->ll4_ipv4ll, timeout_msec);
+ return NM_ACT_STAGE_RETURN_POSTPONE;
+}
- return;
- }
+/*****************************************************************************/
- data = g_slice_new0(AcdData);
- data->configs = configs;
- data->callback = cb;
- data->device = self;
+static void
+_dev_dhcpx_cleanup(NMDevice *self, int addr_family, gboolean reset_dhcp_config, gboolean release)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
- acd_manager = nm_acd_manager_new(nm_device_get_ip_ifindex(self),
- hwaddr_arr,
- length,
- &acd_callbacks,
- data);
- priv->acd.dad_list = g_slist_append(priv->acd.dad_list, acd_manager);
+ priv->dhcp_data_x[IS_IPv4].was_active = FALSE;
- for (i = 0; configs[i]; i++) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, configs[i], &address)
- nm_acd_manager_add_address(acd_manager, address->address);
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL);
- r = nm_acd_manager_start_probe(acd_manager, timeout);
- if (r < 0) {
- _LOGW(LOGD_DEVICE, "acd probe failed");
+ if (!IS_IPv4)
+ priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
- /* DAD could not be started, signal success */
- cb(self, configs, TRUE);
+ nm_clear_g_source_inst(&priv->dhcp_data_x[IS_IPv4].grace_source);
+ priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
- priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager);
- nm_acd_manager_free(acd_manager);
+ if (priv->dhcp_data_x[IS_IPv4].client) {
+ /* Stop any ongoing DHCP transaction on this device */
+ nm_clear_g_signal_handler(priv->dhcp_data_x[IS_IPv4].client,
+ &priv->dhcp_data_x[IS_IPv4].state_sigid);
+ if (!IS_IPv4)
+ nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp6.prefix_sigid);
+ nm_dhcp_client_stop(priv->dhcp_data_x[IS_IPv4].client, release);
+ g_clear_object(&priv->dhcp_data_x[IS_IPv4].client);
}
-}
-
-/*****************************************************************************/
-/* IPv4LL stuff */
-
-static void
-ipv4ll_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (priv->ipv4ll) {
- sd_ipv4ll_set_callback(priv->ipv4ll, NULL, NULL);
- sd_ipv4ll_stop(priv->ipv4ll);
- priv->ipv4ll = sd_ipv4ll_unref(priv->ipv4ll);
+ if (reset_dhcp_config) {
+ if (nm_dbus_object_clear_and_unexport(&priv->dhcp_data_x[IS_IPv4].config))
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
}
-
- nm_clear_g_source(&priv->ipv4ll_timeout);
}
-static NMIP4Config *
-ipv4ll_get_ip4_config(NMDevice *self, guint32 lla)
+static gboolean
+_dev_dhcpx_grace_period_expired(NMDevice *self, int addr_family)
{
- NMIP4Config * config = NULL;
- NMPlatformIP4Address address;
- NMPlatformIP4Route route;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
- config = nm_device_ip4_config_new(self);
- g_assert(config);
+ nm_clear_g_source_inst(&priv->dhcp_data_x[IS_IPv4].grace_source);
+ priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
- memset(&address, 0, sizeof(address));
- nm_platform_ip4_address_set_addr(&address, lla, 16);
- address.addr_source = NM_IP_CONFIG_SOURCE_IP4LL;
- nm_ip4_config_add_address(config, &address);
+ _LOGI(LOGD_DHCPX(IS_IPv4),
+ "DHCPv%c: grace period expired",
+ nm_utils_addr_family_to_char(addr_family));
- /* Add a multicast route for link-local connections: destination= 224.0.0.0, netmask=240.0.0.0 */
- memset(&route, 0, sizeof(route));
- route.network = htonl(0xE0000000L);
- route.plen = 4;
- route.rt_source = NM_IP_CONFIG_SOURCE_IP4LL;
- route.table_coerced = nm_platform_route_table_coerce(nm_device_get_route_table(self, AF_INET));
- route.metric = nm_device_get_route_metric(self, AF_INET);
- nm_ip4_config_add_route(config, &route, NULL);
+ _set_ip_state_check(self, addr_family);
+ return G_SOURCE_REMOVE;
+}
- return config;
+static gboolean
+_dev_dhcpx_grace_period_expired_4(gpointer user_data)
+{
+ return _dev_dhcpx_grace_period_expired(user_data, AF_INET);
}
-static void
-nm_device_handle_ipv4ll_event(sd_ipv4ll *ll, int event, void *data)
+static gboolean
+_dev_dhcpx_grace_period_expired_6(gpointer user_data)
{
- NMDevice * self = data;
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- struct in_addr address;
- NMIP4Config * config;
- int r;
+ return _dev_dhcpx_grace_period_expired(user_data, AF_INET6);
+}
- if (priv->act_request.obj == NULL)
- return;
+static gboolean
+_dev_dhcpx_grace_period_start(NMDevice *self,
+ int addr_family,
+ guint32 timeout_sec,
+ gboolean force_restart)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = (addr_family == AF_INET);
- nm_assert(nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET),
- NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL));
+ /* In any other case (expired lease, assumed connection, etc.),
+ * wait for some time before failing the IP method.
+ */
+ if (!force_restart && priv->dhcp_data_x[IS_IPv4].grace_pending) {
+ /* already pending. */
+ return FALSE;
+ }
- switch (event) {
- case SD_IPV4LL_EVENT_BIND:
- r = sd_ipv4ll_get_address(ll, &address);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
- return;
- }
+ /* Start a grace period equal to the DHCP timeout multiplied
+ * by a constant factor. */
- if (!nm_utils_ip4_address_is_link_local(address.s_addr)) {
- _LOGE(LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_ERROR);
- return;
- }
+ nm_clear_g_source_inst(&priv->dhcp_data_x[IS_IPv4].grace_source);
- config = ipv4ll_get_ip4_config(self, address.s_addr);
- if (config == NULL) {
- _LOGE(LOGD_AUTOIP4, "failed to get IPv4LL config");
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
- return;
- }
+ if (timeout_sec == 0)
+ timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) {
- nm_clear_g_source(&priv->ipv4ll_timeout);
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(config));
- } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- applied_config_init(&priv->dev_ip_config_4, config);
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) {
- _LOGE(LOGD_AUTOIP4, "failed to update IP4 config for autoip change.");
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
- }
- } else
- g_assert_not_reached();
+ nm_assert(timeout_sec > 0);
+ nm_assert(timeout_sec < G_MAXINT32);
- g_object_unref(config);
- break;
- default:
- _LOGW(LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_AUTOIP_FAILED);
- }
-}
+ if (timeout_sec == NM_DHCP_TIMEOUT_INFINITY)
+ _LOGD(LOGD_DHCPX(IS_IPv4),
+ "DHCPv%c: trying to acquire a new lease",
+ nm_utils_addr_family_to_char(addr_family));
+ else {
+ guint timeout_msec;
-static gboolean
-ipv4ll_timeout_cb(gpointer user_data)
-{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ _LOGD(LOGD_DHCPX(IS_IPv4),
+ "DHCPv%c: trying to acquire a new lease within %u seconds",
+ nm_utils_addr_family_to_char(addr_family),
+ timeout_sec);
- if (priv->ipv4ll_timeout) {
- _LOGI(LOGD_AUTOIP4, "IPv4LL configuration timed out.");
- priv->ipv4ll_timeout = 0;
- ipv4ll_cleanup(self);
+ if (timeout_sec < G_MAXUINT / (GRACE_PERIOD_MULTIPLIER * 1000u))
+ timeout_msec = timeout_sec * (GRACE_PERIOD_MULTIPLIER * 1000u);
+ else
+ timeout_msec = G_MAXUINT;
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET);
+ priv->dhcp_data_x[IS_IPv4].grace_source =
+ nm_g_source_attach(nm_g_timeout_source_new(timeout_msec,
+ G_PRIORITY_DEFAULT,
+ IS_IPv4 ? _dev_dhcpx_grace_period_expired_4
+ : _dev_dhcpx_grace_period_expired_6,
+ self,
+ NULL),
+ NULL);
}
- return FALSE;
+ priv->dhcp_data_x[IS_IPv4].grace_pending = TRUE;
+ return TRUE;
}
-static NMActStageReturn
-ipv4ll_start(NMDevice *self)
+static void
+_dev_dhcpx_state_changed(NMDevice * self,
+ int addr_family,
+ NMDhcpState state,
+ const NML3ConfigData *l3cd)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const struct ether_addr *addr;
- int ifindex, r;
- size_t addr_len;
-
- ipv4ll_cleanup(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_merged = NULL;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
- r = sd_ipv4ll_new(&priv->ipv4ll);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
-
- r = sd_ipv4ll_attach_event(priv->ipv4ll, NULL, 0);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ _LOGD(LOGD_DHCPX(IS_IPv4),
+ "new DHCPv%c client state %d",
+ nm_utils_addr_family_to_char(addr_family),
+ (int) state);
- ifindex = nm_device_get_ip_ifindex(self);
- addr = nm_platform_link_get_address(nm_device_get_platform(self), ifindex, &addr_len);
- if (!addr || addr_len != ETH_ALEN) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address");
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ switch (state) {
+ case NM_DHCP_STATE_BOUND:
+ case NM_DHCP_STATE_EXTENDED:
- r = sd_ipv4ll_set_mac(priv->ipv4ll, addr);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ nm_assert(l3cd);
- r = sd_ipv4ll_set_ifindex(priv->ipv4ll, ifindex);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_ifindex() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
+ */
+ if (!IS_IPv4) {
+ if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_6].d,
+ l3cd,
+ &l3cd_merged)) {
+ _LOGD(LOGD_DHCP6, "merged DHCPv6 lease with previous lease");
+ l3cd = l3cd_merged;
+ }
+ }
- r = sd_ipv4ll_set_callback(priv->ipv4ll, nm_device_handle_ipv4ll_event, self);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ nm_clear_g_source_inst(&priv->dhcp_data_x[IS_IPv4].grace_source);
+ priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
- r = sd_ipv4ll_start(priv->ipv4ll);
- if (r < 0) {
- _LOGE(LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r);
- return NM_ACT_STAGE_RETURN_FAILURE;
- }
+ priv->dhcp_data_x[IS_IPv4].is_bad = FALSE;
- _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started");
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), l3cd);
- /* Start a timeout to bound the address attempt */
- priv->ipv4ll_timeout = g_timeout_add_seconds(20, ipv4ll_timeout_cb, self);
- return NM_ACT_STAGE_RETURN_POSTPONE;
-}
+ if (IS_IPv4)
+ nm_device_set_proxy_config(self);
-/*****************************************************************************/
+ nm_dhcp_config_set_lease(priv->dhcp_data_x[IS_IPv4].config, l3cd);
-static void
-ensure_con_ip_config(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMIPConfig * con_ip_config;
+ _set_ip_state_check(self, addr_family);
- if (priv->con_ip_config_x[IS_IPv4])
- return;
+ _dev_l3_cfg_commit(self);
- connection = nm_device_get_applied_connection(self);
- if (!connection)
- return;
+ _dev_l3_notify_change(self, addr_family);
- con_ip_config = nm_device_ip_config_new(self, addr_family);
+ if (!IS_IPv4) {
+ /* FIXME(l3cfg): check where and how to dispatch DHCP change notifications. */
+ nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE,
+ self,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ }
- if (IS_IPv4) {
- nm_ip4_config_merge_setting(NM_IP4_CONFIG(con_ip_config),
- nm_connection_get_setting_ip4_config(connection),
- _prop_get_connection_mdns(self),
- _prop_get_connection_llmnr(self),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family));
- } else {
- nm_ip6_config_merge_setting(NM_IP6_CONFIG(con_ip_config),
- nm_connection_get_setting_ip6_config(connection),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family));
+ break;
+ case NM_DHCP_STATE_TIMEOUT:
+ goto out_fail;
+ case NM_DHCP_STATE_EXPIRE:
+ /* Ignore expiry before we even have a lease (NAK, old lease, etc) */
+ if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
+ break;
+ /* fall-through */
+ case NM_DHCP_STATE_DONE:
+ case NM_DHCP_STATE_FAIL:
+ case NM_DHCP_STATE_TERMINATED:
+ goto out_fail;
+ default:
+ break;
}
- if (nm_device_sys_iface_state_is_external_or_assume(self)) {
- /* For assumed connections ignore all addresses and routes. */
- nm_ip_config_reset_addresses(con_ip_config);
- nm_ip_config_reset_routes(con_ip_config);
- }
+out_fail:
+ _LOGD(LOGD_DHCPX(IS_IPv4),
+ "DHCPv%c failed (ip_state %s, was_active %d)",
+ nm_utils_addr_family_to_char(addr_family),
+ _ip_state_to_string(priv->ip_state_x[IS_IPv4]),
+ (int) priv->dhcp_data_x[IS_IPv4].was_active);
- priv->con_ip_config_x[IS_IPv4] = con_ip_config;
+ _dev_dhcpx_grace_period_start(self, addr_family, 0, FALSE);
+ priv->dhcp_data_x[IS_IPv4].is_bad = TRUE;
+ _set_ip_state_check(self, addr_family);
}
-/*****************************************************************************/
-
static void
-dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
+_dev_dhcpx_state_changed_4(NMDhcpClient * client,
+ NMDhcpState state,
+ const NML3ConfigData *l3cd,
+ gpointer user_data)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->dhcp_data_4.was_active = FALSE;
- nm_clear_g_source(&priv->dhcp_data_4.grace_id);
- priv->dhcp_data_4.grace_pending = FALSE;
- nm_clear_g_free(&priv->dhcp4.pac_url);
-
- if (priv->dhcp_data_4.client) {
- /* Stop any ongoing DHCP transaction on this device */
- nm_clear_g_signal_handler(priv->dhcp_data_4.client, &priv->dhcp_data_4.state_sigid);
+ _dev_dhcpx_state_changed(user_data, AF_INET, state, l3cd);
+}
- if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED)
- nm_dhcp_client_stop(priv->dhcp_data_4.client, release);
+static void
+_dev_dhcpx_state_changed_6(NMDhcpClient * client,
+ NMDhcpState state,
+ const NML3ConfigData *l3cd,
+ gpointer user_data)
+{
+ _dev_dhcpx_state_changed(user_data, AF_INET6, state, l3cd);
+}
- g_clear_object(&priv->dhcp_data_4.client);
- }
+static void
+_dev_dhcp6_prefix_delegated(NMDhcpClient *client, NMPlatformIP6Address *prefix, gpointer user_data)
+{
+ NMDevice *self = NM_DEVICE(user_data);
- if (priv->dhcp_data_4.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- _notify(self, PROP_DHCP4_CONFIG);
- }
+ /* Just re-emit. The device just contributes the prefix to the
+ * pool in NMPolicy, which decides about subnet allocation
+ * on the shared devices. */
+ g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, prefix);
}
static gboolean
-ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit)
+_dev_dhcpx_start(NMDevice *self, int addr_family)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gboolean success;
- gs_unref_object NMIPConfig *composite = NULL;
- NMIPConfig * config;
- gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
- NMConnection * connection;
- gboolean ignore_auto_routes = FALSE;
- gboolean ignore_auto_dns = FALSE;
- gboolean ignore_default_routes = FALSE;
- GSList * iter;
- const char * ip6_addr_gen_token = NULL;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMConnection * connection;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig * s_ip;
+ struct in6_addr ll_addr = IN6ADDR_ANY_INIT;
+ gs_unref_bytes GBytes *hwaddr = NULL;
+ gboolean enforce_duid = FALSE;
+ gs_free char * mud_url_free = NULL;
+ gs_free_error GError *error = NULL;
+ const NMPlatformLink *pllink;
+ guint32 timeout_sec;
+ int ifindex;
+ const char * str;
+
+ nm_assert(priv->dhcp_data_x[IS_IPv4].client == NULL);
if (nm_device_sys_iface_state_is_external(self))
- commit = FALSE;
+ g_return_val_if_reached(TRUE);
connection = nm_device_get_applied_connection(self);
+ g_return_val_if_fail(connection, FALSE);
- /* Apply ignore-auto-routes and ignore-auto-dns settings */
- if (connection) {
- NMSettingIPConfig *s_ip;
+ s_con = nm_connection_get_setting_connection(connection);
+ s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
+ nm_assert(s_con);
+ nm_assert(s_ip);
- s_ip = nm_connection_get_setting_ip_config(connection, addr_family);
- if (s_ip) {
- ignore_auto_routes = nm_setting_ip_config_get_ignore_auto_routes(s_ip);
- ignore_auto_dns = nm_setting_ip_config_get_ignore_auto_dns(s_ip);
+ ifindex = 0;
- /* if the connection has an explicit gateway, we also ignore
- * the default routes from other sources. */
- ignore_default_routes = nm_setting_ip_config_get_never_default(s_ip)
- || nm_setting_ip_config_get_gateway(s_ip);
+ pllink = nm_l3cfg_get_pllink(priv->l3cfg, TRUE);
+ if (pllink) {
+ ifindex = pllink->ifindex;
+ nm_assert(ifindex > 0);
+ nm_assert(ifindex == nm_device_get_ip_ifindex(self));
+ }
- if (!IS_IPv4) {
- NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG(s_ip);
+ if (ifindex <= 0)
+ g_return_val_if_reached(TRUE);
- if (nm_setting_ip6_config_get_addr_gen_mode(s_ip6)
- == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64)
- ip6_addr_gen_token = nm_setting_ip6_config_get_token(s_ip6);
- }
+ hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
+
+ if (!IS_IPv4) {
+ if (!hwaddr) {
+ _LOGD(LOGD_DHCP6, "dhcp6: cannot start DHCP with no suitable interface");
+ return FALSE;
}
}
- composite = nm_device_ip_config_new(self, addr_family);
-
- if (!IS_IPv4) {
- nm_ip6_config_set_privacy(NM_IP6_CONFIG(composite),
- priv->ndisc ? priv->ndisc_use_tempaddr
- : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+ request_broadcast = FALSE;
+ if (pllink) {
+ str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink),
+ "ID_NET_DHCP_BROADCAST");
+ if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) {
+ /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces
+ * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast
+ * messages while not fully configured.
+ */
+ request_broadcast = TRUE;
+ }
}
- init_ip_config_dns_priority(self, composite);
+ timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
- if (commit) {
- if (priv->queued_ip_config_id_x[IS_IPv4])
- update_ext_ip_config(self, addr_family, FALSE);
- ensure_con_ip_config(self, addr_family);
- }
+ _dev_dhcpx_grace_period_start(self, addr_family, timeout_sec, TRUE);
if (!IS_IPv4) {
- if (commit && priv->ipv6ll_has) {
- const NMPlatformIP6Address ll_a = {
- .address = priv->ipv6ll_addr,
- .plen = 64,
- .addr_source = NM_IP_CONFIG_SOURCE_IP6LL,
- };
- const NMPlatformIP6Route ll_r = {
- .network.s6_addr16[0] = htons(0xfe80u),
- .plen = 64,
- .metric = nm_device_get_route_metric(self, addr_family),
- .rt_source = NM_IP_CONFIG_SOURCE_IP6LL,
- };
-
- nm_assert(IN6_IS_ADDR_LINKLOCAL(&priv->ipv6ll_addr));
-
- nm_ip6_config_add_address(NM_IP6_CONFIG(composite), &ll_a);
- nm_ip6_config_add_route(NM_IP6_CONFIG(composite), &ll_r, NULL);
+ if (!_dev_ll6_start(self, &ll_addr)) {
+ /* wait for the LL address to show up */
+ return TRUE;
}
}
- if (commit) {
- gboolean v;
+ if (IS_IPv4) {
+ gs_unref_bytes GBytes *bcast_hwaddr = NULL;
+ gs_unref_bytes GBytes *client_id = NULL;
+ gs_unref_bytes GBytes *vendor_class_identifier = NULL;
+ const char *const * reject_servers;
- v = default_route_metric_penalty_detect(self, addr_family);
- if (IS_IPv4)
- priv->default_route_metric_penalty_ip4_has = v;
- else
- priv->default_route_metric_penalty_ip6_has = v;
- }
+ client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr);
+ vendor_class_identifier =
+ _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip));
+ reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip, NULL);
- /* Merge all the IP configs into the composite config */
+ bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
- if (IS_IPv4) {
- config = applied_config_get_current(&priv->dev_ip_config_4);
- if (config) {
- nm_ip4_config_merge(
- NM_IP4_CONFIG(composite),
- NM_IP4_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+ priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4(
+ nm_dhcp_manager_get(),
+ nm_netns_get_multi_idx(nm_device_get_netns(self)),
+ nm_device_get_ip_iface(self),
+ nm_device_get_ip_ifindex(self),
+ hwaddr,
+ bcast_hwaddr,
+ nm_connection_get_uuid(connection),
+ request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE,
+ nm_setting_ip_config_get_dhcp_send_hostname(s_ip),
+ nm_setting_ip_config_get_dhcp_hostname(s_ip),
+ nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip)),
+ _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
+ _prop_get_connection_mud_url(self, s_con, &mud_url_free),
+ client_id,
+ timeout_sec,
+ priv->dhcp_anycast_address,
+ NULL,
+ vendor_class_identifier,
+ reject_servers,
+ &error);
+ } else {
+ gs_unref_bytes GBytes *duid = NULL;
+ gboolean iaid_explicit;
+ guint32 iaid;
+
+ iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_explicit);
+ duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
+
+ priv->dhcp_data_6.client = nm_dhcp_manager_start_ip6(
+ nm_dhcp_manager_get(),
+ nm_device_get_multi_index(self),
+ nm_device_get_ip_iface(self),
+ ifindex,
+ &ll_addr,
+ nm_connection_get_uuid(connection),
+ (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY
+ : NM_DHCP_CLIENT_FLAGS_NONE,
+ nm_setting_ip_config_get_dhcp_send_hostname(s_ip),
+ nm_setting_ip_config_get_dhcp_hostname(s_ip),
+ _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
+ _prop_get_connection_mud_url(self, s_con, &mud_url_free),
+ duid,
+ enforce_duid,
+ iaid,
+ iaid_explicit,
+ _prop_get_ipvx_dhcp_timeout(self, AF_INET6),
+ priv->dhcp_anycast_address,
+ nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip)),
+ priv->dhcp6.needed_prefixes,
+ &error);
}
- if (!IS_IPv4) {
- config = applied_config_get_current(&priv->ac_ip6_config);
- if (config) {
- nm_ip6_config_merge(
- NM_IP6_CONFIG(composite),
- NM_IP6_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+ if (nm_device_sys_iface_state_is_external_or_assume(self))
+ priv->dhcp_data_x[IS_IPv4].was_active = TRUE;
+
+ if (!priv->dhcp_data_x[IS_IPv4].client) {
+ _LOGW(LOGD_DHCPX(IS_IPv4),
+ "dhcp%c: failure to start DHCP client: %s",
+ nm_utils_addr_family_to_char(addr_family),
+ error->message);
+ _dev_dhcpx_cleanup(self, addr_family, TRUE, TRUE);
+ return FALSE;
}
+ priv->dhcp_data_x[IS_IPv4].state_sigid = g_signal_connect(
+ priv->dhcp_data_x[IS_IPv4].client,
+ NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
+ IS_IPv4 ? G_CALLBACK(_dev_dhcpx_state_changed_4) : G_CALLBACK(_dev_dhcpx_state_changed_6),
+ self);
if (!IS_IPv4) {
- config = applied_config_get_current(&priv->dhcp6.ip6_config);
- if (config) {
- nm_ip6_config_merge(
- NM_IP6_CONFIG(composite),
- NM_IP6_CONFIG(config),
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+ priv->dhcp6.prefix_sigid = g_signal_connect(priv->dhcp_data_6.client,
+ NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
+ G_CALLBACK(_dev_dhcp6_prefix_delegated),
+ self);
}
- for (iter = priv->vpn_configs_x[IS_IPv4]; iter; iter = iter->next)
- nm_ip_config_merge(composite, iter->data, NM_IP_CONFIG_MERGE_DEFAULT, 0);
+ if (!priv->dhcp_data_x[IS_IPv4].config) {
+ priv->dhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family);
+ nm_dbus_object_export(priv->dhcp_data_x[IS_IPv4].config);
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
+ } else
+ nm_dhcp_config_set_lease(priv->dhcp_data_x[IS_IPv4].config, NULL);
- if (priv->ext_ip_config_x[IS_IPv4])
- nm_ip_config_merge(composite,
- priv->ext_ip_config_x[IS_IPv4],
- NM_IP_CONFIG_MERGE_EXTERNAL,
- 0);
+ return TRUE;
+}
- /* Merge WWAN config *last* to ensure modem-given settings overwrite
- * any external stuff set by pppd or other scripts.
- */
- config = applied_config_get_current(&priv->dev2_ip_config_x[IS_IPv4]);
- if (config) {
- nm_ip_config_merge(composite,
- config,
- (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0)
- | (ignore_default_routes ? NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES : 0)
- | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0),
- default_route_metric_penalty_get(self, addr_family));
- }
+static void
+_dev_dhcp6_set_dhcp_level(NMDevice *self, NMNDiscDHCPLevel dhcp_level)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (!IS_IPv4) {
- if (priv->rt6_temporary_not_available) {
- const NMPObject *o;
- GHashTableIter hiter;
-
- g_hash_table_iter_init(&hiter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&hiter, (gpointer *) &o, NULL)) {
- nm_ip6_config_add_route(NM_IP6_CONFIG(composite),
- NMP_OBJECT_CAST_IP6_ROUTE(o),
- NULL);
- }
- }
- }
+ if (priv->dhcp6.mode == dhcp_level)
+ return;
- /* Merge user overrides into the composite config. For assumed connections,
- * con_ip_config_x is empty. */
- if (priv->con_ip_config_x[IS_IPv4]) {
- nm_ip_config_merge(composite,
- priv->con_ip_config_x[IS_IPv4],
- NM_IP_CONFIG_MERGE_DEFAULT,
- default_route_metric_penalty_get(self, addr_family));
- }
+ _LOGD(LOGD_DEVICE | LOGD_DHCP6, "reset DHCPv6 level to %d", (int) dhcp_level);
- if (commit) {
- gboolean is_vrf;
+ _dev_dhcpx_cleanup(self, AF_INET6, TRUE, TRUE);
- is_vrf = priv->master && nm_device_get_device_type(priv->master) == NM_DEVICE_TYPE_VRF;
+ priv->dhcp6.mode = dhcp_level;
+ if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_NONE)
+ return;
- if (IS_IPv4) {
- nm_ip4_config_add_dependent_routes(NM_IP4_CONFIG(composite),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family),
- is_vrf,
- &ip4_dev_route_blacklist);
- } else {
- nm_ip6_config_add_dependent_routes(NM_IP6_CONFIG(composite),
- nm_device_get_route_table(self, addr_family),
- nm_device_get_route_metric(self, addr_family),
- is_vrf);
- }
- }
+ _dev_dhcpx_start(self, AF_INET6);
+}
- if (IS_IPv4) {
- if (commit) {
- if (NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit)
- NM_DEVICE_GET_CLASS(self)->ip4_config_pre_commit(self, NM_IP4_CONFIG(composite));
- }
- }
+/*****************************************************************************/
- if (!IS_IPv4) {
- NMUtilsIPv6IfaceId iid;
+gboolean
+nm_device_dhcp_renew(NMDevice *self, int addr_family, gboolean release)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
- if (commit && priv->ndisc_started && ip6_addr_gen_token
- && nm_utils_ipv6_interface_identifier_get_from_token(&iid, ip6_addr_gen_token)) {
- set_ipv6_token(self, iid, ip6_addr_gen_token);
- }
- }
+ if (!priv->dhcp_data_x[IS_IPv4].client)
+ g_return_val_if_reached(FALSE);
- success =
- nm_device_set_ip_config(self, addr_family, composite, commit, ip4_dev_route_blacklist);
- if (commit) {
- if (IS_IPv4)
- priv->v4_commit_first_time = FALSE;
- else
- priv->v6_commit_first_time = FALSE;
- }
+ _LOGI(LOGD_DHCPX(IS_IPv4),
+ "DHCPv%c lease renewal requested",
+ nm_utils_addr_family_to_char(addr_family));
- return success;
+ _dev_dhcpx_cleanup(self, addr_family, FALSE, release);
+
+ return _dev_dhcpx_start(self, addr_family);
}
+/*****************************************************************************/
+
static gboolean
-dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound)
+connection_ip_method_requires_carrier(NMConnection *connection,
+ int addr_family,
+ gboolean * out_ip_enabled)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_free_error GError *error = NULL;
-
- g_return_val_if_fail(config, FALSE);
-
- applied_config_init(&priv->dev_ip_config_4, config);
+ const char *method;
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) {
- _LOGW(LOGD_DHCP4, "failed to update IPv4 config for DHCP change.");
- return FALSE;
- }
+ method = nm_utils_get_ip_config_method(connection, addr_family);
- /* TODO: we should perform DAD again whenever we obtain a
- * new lease after an expiry. But what should we do if
- * a duplicate address is detected? Fail the connection;
- * restart DHCP; continue without an address? */
- if (bound && !nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) {
- _LOGW(LOGD_DHCP4, "error accepting lease: %s", error->message);
- return FALSE;
+ if (NM_IS_IPv4(addr_family)) {
+ NM_SET_OUT(out_ip_enabled, !nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED));
+ return NM_IN_STRSET(method,
+ NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL);
}
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, self, NULL, NULL, NULL, NULL);
-
- return TRUE;
+ NM_SET_OUT(out_ip_enabled,
+ !NM_IN_STRSET(method,
+ NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
+ NM_SETTING_IP6_CONFIG_METHOD_DISABLED));
+ return NM_IN_STRSET(method,
+ NM_SETTING_IP6_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP6_CONFIG_METHOD_DHCP,
+ NM_SETTING_IP6_CONFIG_METHOD_SHARED,
+ NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL);
}
static gboolean
-dhcp_grace_period_expired(NMDevice *self, int addr_family)
+connection_requires_carrier(NMConnection *connection)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMSettingIPConfig * s_ip4, *s_ip6;
+ NMSettingConnection *s_con;
+ gboolean ip4_carrier_wanted, ip6_carrier_wanted;
+ gboolean ip4_used = FALSE, ip6_used = FALSE;
- priv->dhcp_data_x[IS_IPv4].grace_id = 0;
- priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
+ /* We can progress to IP_CONFIG now, so that we're enslaved.
+ * That may actually cause carrier to go up and thus continue activation. */
+ s_con = nm_connection_get_setting_connection(connection);
+ if (nm_setting_connection_get_master(s_con))
+ return FALSE;
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: grace period expired",
- nm_utils_addr_family_to_char(addr_family));
+ ip4_carrier_wanted = connection_ip_method_requires_carrier(connection, AF_INET, &ip4_used);
+ if (ip4_carrier_wanted) {
+ /* If IPv4 wants a carrier and cannot fail, the whole connection
+ * requires a carrier regardless of the IPv6 method.
+ */
+ s_ip4 = nm_connection_get_setting_ip4_config(connection);
+ if (s_ip4 && !nm_setting_ip_config_get_may_fail(s_ip4))
+ return TRUE;
+ }
- nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED);
- /* If the device didn't fail, the DHCP client will continue */
+ ip6_carrier_wanted = connection_ip_method_requires_carrier(connection, AF_INET6, &ip6_used);
+ if (ip6_carrier_wanted) {
+ /* If IPv6 wants a carrier and cannot fail, the whole connection
+ * requires a carrier regardless of the IPv4 method.
+ */
+ s_ip6 = nm_connection_get_setting_ip6_config(connection);
+ if (s_ip6 && !nm_setting_ip_config_get_may_fail(s_ip6))
+ return TRUE;
+ }
- return G_SOURCE_REMOVE;
+ /* If an IP version wants a carrier and the other IP version isn't
+ * used, the connection requires carrier since it will just fail without one.
+ */
+ if (ip4_carrier_wanted && !ip6_used)
+ return TRUE;
+ if (ip6_carrier_wanted && !ip4_used)
+ return TRUE;
+
+ /* If both want a carrier, the whole connection wants a carrier */
+ return ip4_carrier_wanted && ip6_carrier_wanted;
}
static gboolean
-dhcp_grace_period_expired_4(gpointer user_data)
+have_any_ready_slaves(NMDevice *self)
{
- return dhcp_grace_period_expired(user_data, AF_INET);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ SlaveInfo * info;
+ CList * iter;
+
+ /* Any enslaved slave is "ready" in the generic case as it's
+ * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2
+ * properties set up.
+ */
+ c_list_for_each (iter, &priv->slaves) {
+ info = c_list_entry(iter, SlaveInfo, lst_slave);
+ if (NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved)
+ return TRUE;
+ }
+ return FALSE;
}
-static gboolean
-dhcp_grace_period_expired_6(gpointer user_data)
+/*****************************************************************************/
+<<<<<<< HEAD
+/* DHCPv6 stuff */
+
+static void
+dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
{
- return dhcp_grace_period_expired(user_data, AF_INET6);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ priv->dhcp_data_6.was_active = FALSE;
+ priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
+ applied_config_clear(&priv->dhcp6.ip6_config);
+ nm_clear_g_free(&priv->dhcp6.event_id);
+ nm_clear_g_source(&priv->dhcp_data_6.grace_id);
+ priv->dhcp_data_6.grace_pending = FALSE;
+
+ if (priv->dhcp_data_6.client) {
+ nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp_data_6.state_sigid);
+ nm_clear_g_signal_handler(priv->dhcp_data_6.client, &priv->dhcp6.prefix_sigid);
+
+ if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED)
+ nm_dhcp_client_stop(priv->dhcp_data_6.client, release);
+
+ g_clear_object(&priv->dhcp_data_6.client);
+ }
+
+ if (priv->dhcp_data_6.config) {
+ nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
+ _notify(self, PROP_DHCP6_CONFIG);
+ }
}
static gboolean
-dhcp_grace_period_start(NMDevice *self, int addr_family)
+dhcp6_lease_change(NMDevice *self)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- guint32 timeout;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMSettingsConnection *settings_connection;
- /* In any other case (expired lease, assumed connection, etc.),
- * wait for some time before failing the IP method.
- */
- if (priv->dhcp_data_x[IS_IPv4].grace_pending) {
- /* already pending. */
+ if (!applied_config_get_current(&priv->dhcp6.ip6_config)) {
+ _LOGW(LOGD_DHCP6, "failed to get DHCPv6 config for rebind");
return FALSE;
}
- /* Start a grace period equal to the DHCP timeout multiplied
- * by a constant factor. */
- timeout = _prop_get_ipvx_dhcp_timeout(self, addr_family);
- if (timeout == NM_DHCP_TIMEOUT_INFINITY)
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: trying to acquire a new lease",
- nm_utils_addr_family_to_char(addr_family));
- else {
- timeout = dhcp_grace_period_from_timeout(timeout);
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: trying to acquire a new lease within %u seconds",
- nm_utils_addr_family_to_char(addr_family),
- timeout);
- nm_assert(!priv->dhcp_data_x[IS_IPv4].grace_id);
- priv->dhcp_data_x[IS_IPv4].grace_id = g_timeout_add_seconds(
- timeout,
- IS_IPv4 ? dhcp_grace_period_expired_4 : dhcp_grace_period_expired_6,
- self);
+ g_assert(priv->dhcp_data_6.client); /* sanity check */
+
+ settings_connection = nm_device_get_settings_connection(self);
+ g_assert(settings_connection);
+
+ /* Apply the updated config */
+ if (!ip_config_merge_and_apply(self, AF_INET6, TRUE)) {
+ _LOGW(LOGD_DHCP6, "failed to update IPv6 config in response to DHCP event");
+ return FALSE;
}
- priv->dhcp_data_x[IS_IPv4].grace_pending = TRUE;
+ nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, self, NULL, NULL, NULL, NULL);
return TRUE;
}
+
static void
-dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state)
+dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gboolean is_dhcp_managed;
- _LOGD(LOGD_DHCP4,
- "DHCPv4 failed (ip_state %s, was_active %d)",
- _ip_state_to_string(priv->ip_state_4),
- priv->dhcp_data_4.was_active);
+ _LOGD(LOGD_DHCP6,
+ "DHCPv6 failed (ip_state %s, was_active %d)",
+ _ip_state_to_string(priv->ip_state_6),
+ priv->dhcp_data_6.was_active);
/* The client is always left running after a failure. */
/* Nothing to do if we failed before... */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL)
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL)
goto clear_config;
- /* ... and also if there are static addresses configured
- * on the interface.
- */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_4
- && nm_ip4_config_get_num_addresses(priv->con_ip_config_4) > 0)
- goto clear_config;
+ is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED);
- /* Fail the method when one of the following is true:
- * 1) the DHCP client terminated: it does not make sense to start a grace
- * period without a client running;
- * 2) we failed to get an initial lease AND the client was
- * not active before.
- */
- if (dhcp_state == NM_DHCP_STATE_TERMINATED
- || (!priv->dhcp_data_4.was_active && priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)) {
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET);
- return;
- }
+ if (is_dhcp_managed) {
+ /* ... and also if there are static addresses configured
+ * on the interface.
+ */
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE && priv->con_ip_config_6
+ && nm_ip6_config_get_num_addresses(priv->con_ip_config_6))
+ goto clear_config;
- if (dhcp_grace_period_start(self, AF_INET))
- goto clear_config;
+ /* Fail the method when one of the following is true:
+ * 1) the DHCP client terminated: it does not make sense to start a grace
+ * period without a client running;
+ * 2) we failed to get an initial lease AND the client was
+ * not active before.
+ */
+ if (dhcp_state == NM_DHCP_STATE_TERMINATED
+ || (!priv->dhcp_data_6.was_active && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)) {
+ nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
+ return;
+ }
+ if (dhcp_grace_period_start(self, AF_INET6))
+ goto clear_config;
+ } else {
+ /* not a hard failure; just live with the RA info */
+ dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE);
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)
+ nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+ }
return;
clear_config:
/* The previous configuration is no longer valid */
- if (priv->dhcp_data_4.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET);
- _notify(self, PROP_DHCP4_CONFIG);
- }
-}
-
-static void
-dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (success) {
- nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(configs[1]));
- } else {
- nm_dhcp_client_decline(priv->dhcp_data_4.client, "Address conflict detected", NULL);
- nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE);
+ if (priv->dhcp_data_6.config) {
+ nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
+ priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6);
+ _notify(self, PROP_DHCP6_CONFIG);
}
}
static void
-dhcp4_state_changed(NMDhcpClient *client,
+dhcp6_state_changed(NMDhcpClient *client,
NMDhcpState state,
- NMIP4Config * ip4_config,
+ NMIP6Config * ip6_config,
GHashTable * options,
gpointer user_data)
{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP4Config * manual, **configs;
- NMConnection * connection;
+ NMDevice * self = NM_DEVICE(user_data);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ gs_free char * event_id = NULL;
- g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET);
- g_return_if_fail(!ip4_config || NM_IS_IP4_CONFIG(ip4_config));
+ g_return_if_fail(nm_dhcp_client_get_addr_family(client) == AF_INET6);
+ g_return_if_fail(!ip6_config || NM_IS_IP6_CONFIG(ip6_config));
- _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", state);
+ _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", state);
switch (state) {
case NM_DHCP_STATE_BOUND:
case NM_DHCP_STATE_EXTENDED:
- if (!ip4_config) {
- _LOGW(LOGD_DHCP4, "failed to get IPv4 config in response to DHCP event.");
- dhcp4_fail(self, state);
- break;
- }
-
- nm_clear_g_source(&priv->dhcp_data_4.grace_id);
- priv->dhcp_data_4.grace_pending = FALSE;
-
- /* After some failures, we have been able to renew the lease:
- * update the ip state
+ nm_clear_g_source(&priv->dhcp_data_6.grace_id);
+ priv->dhcp_data_6.grace_pending = FALSE;
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
*/
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_FAIL)
- _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_CONF);
-
- g_free(priv->dhcp4.pac_url);
- priv->dhcp4.pac_url = g_strdup(g_hash_table_lookup(options, "wpad"));
- nm_device_set_proxy_config(self, priv->dhcp4.pac_url);
- nm_dhcp_config_set_options(priv->dhcp_data_4.config, options);
- _notify(self, PROP_DHCP4_CONFIG);
+ event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) {
- connection = nm_device_get_applied_connection(self);
- g_assert(connection);
+ if (ip6_config && event_id && priv->dhcp6.event_id
+ && nm_streq(event_id, priv->dhcp6.event_id)) {
+ NMDedupMultiIter ipconf_iter;
+ const NMPlatformIP6Address *a;
- manual = nm_device_ip4_config_new(self);
- nm_ip4_config_merge_setting(manual,
- nm_connection_get_setting_ip4_config(connection),
- NM_SETTING_CONNECTION_MDNS_DEFAULT,
- NM_SETTING_CONNECTION_LLMNR_DEFAULT,
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
+ nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6_config, &a)
+ applied_config_add_address(&priv->dhcp6.ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(a));
+ } else {
+ nm_clear_g_free(&priv->dhcp6.event_id);
+ if (ip6_config) {
+ applied_config_init(&priv->dhcp6.ip6_config, ip6_config);
+ priv->dhcp6.event_id = g_strdup(event_id);
+ nm_dhcp_config_set_options(priv->dhcp_data_6.config, options);
+ _notify(self, PROP_DHCP6_CONFIG);
+ } else
+ applied_config_clear(&priv->dhcp6.ip6_config);
+ }
- configs = g_new0(NMIP4Config *, 3);
- configs[0] = manual;
- configs[1] = g_object_ref(ip4_config);
+ /* After long time we have been able to renew the lease:
+ * update the ip state
+ */
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_FAIL)
+ _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF);
- ipv4_dad_start(self, configs, dhcp4_dad_cb);
- } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- if (dhcp4_lease_change(self, ip4_config, state == NM_DHCP_STATE_BOUND))
- nm_device_update_metered(self);
- else
- dhcp4_fail(self, state);
- }
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) {
+ if (!applied_config_get_current(&priv->dhcp6.ip6_config)) {
+ nm_device_ip_method_failed(self, AF_INET6, NM_DEVICE_STATE_REASON_DHCP_FAILED);
+ break;
+ }
+ nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+ } else if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE)
+ if (!dhcp6_lease_change(self))
+ dhcp6_fail(self, state);
break;
case NM_DHCP_STATE_TIMEOUT:
- dhcp4_fail(self, state);
+ if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED)
+ dhcp6_fail(self, state);
+ else {
+ /* not a hard failure; just live with the RA info */
+ dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, FALSE);
+ if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF)
+ nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+ }
break;
case NM_DHCP_STATE_EXPIRE:
/* Ignore expiry before we even have a lease (NAK, old lease, etc) */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
+ if (priv->ip_state_6 != NM_DEVICE_IP_STATE_CONF)
+ dhcp6_fail(self, state);
+ break;
+ case NM_DHCP_STATE_TERMINATED:
+ /* In IPv6 info-only mode, the client doesn't handle leases so it
+ * may exit right after getting a response from the server. That's
+ * normal. In that case we just ignore the exit.
+ */
+ if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF)
break;
/* fall-through */
case NM_DHCP_STATE_DONE:
case NM_DHCP_STATE_FAIL:
- case NM_DHCP_STATE_TERMINATED:
- dhcp4_fail(self, state);
+ dhcp6_fail(self, state);
break;
default:
break;
}
}
-static NMActStageReturn
-dhcp4_start(NMDevice *self)
+static void
+dhcp6_prefix_delegated(NMDhcpClient *client, NMPlatformIP6Address *prefix, gpointer user_data)
+{
+ NMDevice *self = NM_DEVICE(user_data);
+
+ /* Just re-emit. The device just contributes the prefix to the
+ * pool in NMPolicy, which decides about subnet allocation
+ * on the shared devices. */
+ g_signal_emit(self, signals[IP6_PREFIX_DELEGATED], 0, prefix);
+}
+
+/*****************************************************************************/
+
+static gboolean
+dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
{
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingIPConfig *s_ip4;
- gs_unref_bytes GBytes *vendor_class_identifier = NULL;
- gs_unref_bytes GBytes *hwaddr = NULL;
- gs_unref_bytes GBytes *bcast_hwaddr = NULL;
- gs_unref_bytes GBytes *client_id = NULL;
- gs_free char * mud_url_free = NULL;
- NMConnection * connection;
- NMSettingConnection * s_con;
- GError * error = NULL;
- const NMPlatformLink * pllink;
- const char *const * reject_servers;
- gboolean request_broadcast;
- const char * str;
+ NMSettingIPConfig *s_ip6;
+ gs_unref_bytes GBytes *hwaddr = NULL;
+ gs_unref_bytes GBytes * duid = NULL;
+ gboolean enforce_duid = FALSE;
+ const NMPlatformLink * pllink;
+ gs_free char * mud_url_free = NULL;
+ GError * error = NULL;
+ guint32 iaid;
+ gboolean iaid_explicit;
+ NMSettingConnection * s_con;
+ const NMPlatformIP6Address *ll_addr = NULL;
- connection = nm_device_get_applied_connection(self);
g_return_val_if_fail(connection, FALSE);
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
-
+ s_ip6 = nm_connection_get_setting_ip6_config(connection);
+ nm_assert(s_ip6);
s_con = nm_connection_get_setting_connection(connection);
nm_assert(s_con);
- /* Clear old exported DHCP options */
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- priv->dhcp_data_4.config = nm_dhcp_config_new(AF_INET);
+ if (priv->ext_ip6_config_captured) {
+ ll_addr = nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+ | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
+ }
- request_broadcast = FALSE;
+ if (!ll_addr) {
+ _LOGW(LOGD_DHCP6, "can't start DHCPv6: no link-local address");
+ return FALSE;
+ }
pllink = nm_platform_link_get(nm_device_get_platform(self), nm_device_get_ip_ifindex(self));
- if (pllink) {
- hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
- bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
-
- str = nmp_object_link_udev_device_get_property_value(NMP_OBJECT_UP_CAST(pllink),
- "ID_NET_DHCP_BROADCAST");
- if (str && _nm_utils_ascii_str_to_bool(str, FALSE)) {
- /* Use the device property ID_NET_DHCP_BROADCAST setting, which may be set for interfaces
- * requiring that the DHCPOFFER message is being broadcast because they can't handle unicast
- * messages while not fully configured.
- */
- request_broadcast = TRUE;
- }
- }
+ if (pllink)
+ hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
- client_id = _prop_get_ipv4_dhcp_client_id(self, connection, hwaddr);
- vendor_class_identifier =
- _prop_get_ipv4_dhcp_vendor_class_identifier(self, NM_SETTING_IP4_CONFIG(s_ip4));
- reject_servers = nm_setting_ip_config_get_dhcp_reject_servers(s_ip4, NULL);
+ iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, TRUE, &iaid_explicit);
+ duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
- g_warn_if_fail(priv->dhcp_data_4.client == NULL);
- priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4(
+ priv->dhcp_data_6.client = nm_dhcp_manager_start_ip6(
nm_dhcp_manager_get(),
- nm_netns_get_multi_idx(nm_device_get_netns(self)),
+ nm_device_get_multi_index(self),
nm_device_get_ip_iface(self),
nm_device_get_ip_ifindex(self),
- hwaddr,
- bcast_hwaddr,
+ &ll_addr->address,
nm_connection_get_uuid(connection),
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET),
- request_broadcast ? NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST : NM_DHCP_CLIENT_FLAGS_NONE,
- nm_setting_ip_config_get_dhcp_send_hostname(s_ip4),
- nm_setting_ip_config_get_dhcp_hostname(s_ip4),
- nm_setting_ip4_config_get_dhcp_fqdn(NM_SETTING_IP4_CONFIG(s_ip4)),
- _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET),
+ nm_device_get_route_table(self, AF_INET6),
+ nm_device_get_route_metric(self, AF_INET6),
+ (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY
+ : NM_DHCP_CLIENT_FLAGS_NONE,
+ nm_setting_ip_config_get_dhcp_send_hostname(s_ip6),
+ nm_setting_ip_config_get_dhcp_hostname(s_ip6),
+ _prop_get_ipvx_dhcp_hostname_flags(self, AF_INET6),
_prop_get_connection_mud_url(self, s_con, &mud_url_free),
- client_id,
- _prop_get_ipvx_dhcp_timeout(self, AF_INET),
+ duid,
+ enforce_duid,
+ iaid,
+ iaid_explicit,
+ _prop_get_ipvx_dhcp_timeout(self, AF_INET6),
priv->dhcp_anycast_address,
- NULL,
- vendor_class_identifier,
- reject_servers,
+ nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)),
+ priv->dhcp6.needed_prefixes,
&error);
- if (!priv->dhcp_data_4.client) {
- _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message);
+ if (!priv->dhcp_data_6.client) {
+ _LOGW(LOGD_DHCP6, "failure to start DHCPv6: %s", error->message);
g_clear_error(&error);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (nm_device_sys_iface_state_is_external_or_assume(self))
+ priv->dhcp_data_6.was_active = TRUE;
+ return FALSE;
}
- priv->dhcp_data_4.state_sigid = g_signal_connect(priv->dhcp_data_4.client,
+ priv->dhcp_data_6.state_sigid = g_signal_connect(priv->dhcp_data_6.client,
NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
- G_CALLBACK(dhcp4_state_changed),
+ G_CALLBACK(dhcp6_state_changed),
self);
+ priv->dhcp6.prefix_sigid = g_signal_connect(priv->dhcp_data_6.client,
+ NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
+ G_CALLBACK(dhcp6_prefix_delegated),
+ self);
if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_4.was_active = TRUE;
+ priv->dhcp_data_6.was_active = TRUE;
- /* DHCP devices will be notified by the DHCP manager when stuff happens */
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ return TRUE;
}
-gboolean
-nm_device_dhcp4_renew(NMDevice *self, gboolean release)
+static gboolean
+dhcp6_start(NMDevice *self, gboolean wait_for_ll)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMConnection * connection;
- g_return_val_if_fail(priv->dhcp_data_4.client != NULL, FALSE);
-
- _LOGI(LOGD_DHCP4, "DHCPv4 lease renewal requested");
-
- /* Terminate old DHCP instance and release the old lease */
- dhcp4_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release);
-
- /* Start DHCP again on the interface */
- return dhcp4_start(self) != NM_ACT_STAGE_RETURN_FAILURE;
-}
-
-/*****************************************************************************/
-
-static NMIP4Config *
-shared4_new_config(NMDevice *self, NMConnection *connection)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP4Config * config;
- NMSettingIPConfig * s_ip4;
- NMPlatformIP4Address address = {
- .addr_source = NM_IP_CONFIG_SOURCE_SHARED,
- };
+ nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
+ priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6);
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(connection, NULL);
+ nm_assert(!applied_config_get_current(&priv->dhcp6.ip6_config));
+ applied_config_clear(&priv->dhcp6.ip6_config);
+ nm_clear_g_free(&priv->dhcp6.event_id);
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
- /* Use the first user-supplied address */
- NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0);
- in_addr_t a;
+ connection = nm_device_get_applied_connection(self);
+ g_return_val_if_fail(connection, FALSE);
- nm_ip_address_get_address_binary(user, &a);
- nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user));
- nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
- } else {
- if (!priv->shared_ip_handle)
- priv->shared_ip_handle = nm_netns_shared_ip_reserve(nm_device_get_netns(self));
- nm_platform_ip4_address_set_addr(&address, priv->shared_ip_handle->addr, 24);
+ if (wait_for_ll) {
+ /* ensure link local is ready... */
+ if (!linklocal6_start(self)) {
+ /* wait for the LL address to show up */
+ return TRUE;
+ }
+ /* already have the LL address; kick off DHCP */
}
- config = nm_device_ip4_config_new(self);
- nm_ip4_config_add_address(config, &address);
-
- return config;
-}
-
-/*****************************************************************************/
-
-static gboolean
-connection_ip_method_requires_carrier(NMConnection *connection,
- int addr_family,
- gboolean * out_ip_enabled)
-{
- const char *method;
-
- method = nm_utils_get_ip_config_method(connection, addr_family);
-
- if (NM_IS_IPv4(addr_family)) {
- NM_SET_OUT(out_ip_enabled, !nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED));
- return NM_IN_STRSET(method,
- NM_SETTING_IP4_CONFIG_METHOD_AUTO,
- NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL);
- }
+ if (!dhcp6_start_with_link_ready(self, connection))
+ return FALSE;
- NM_SET_OUT(out_ip_enabled,
- !NM_IN_STRSET(method,
- NM_SETTING_IP6_CONFIG_METHOD_IGNORE,
- NM_SETTING_IP6_CONFIG_METHOD_DISABLED));
- return NM_IN_STRSET(method,
- NM_SETTING_IP6_CONFIG_METHOD_AUTO,
- NM_SETTING_IP6_CONFIG_METHOD_DHCP,
- NM_SETTING_IP6_CONFIG_METHOD_SHARED,
- NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL);
+ return TRUE;
}
-static gboolean
-connection_requires_carrier(NMConnection *connection)
+gboolean
+nm_device_dhcp6_renew(NMDevice *self, gboolean release)
{
- NMSettingIPConfig * s_ip4, *s_ip6;
- NMSettingConnection *s_con;
- gboolean ip4_carrier_wanted, ip6_carrier_wanted;
- gboolean ip4_used = FALSE, ip6_used = FALSE;
-
- /* We can progress to IP_CONFIG now, so that we're enslaved.
- * That may actually cause carrier to go up and thus continue activation. */
- s_con = nm_connection_get_setting_connection(connection);
- if (nm_setting_connection_get_master(s_con))
- return FALSE;
-
- ip4_carrier_wanted = connection_ip_method_requires_carrier(connection, AF_INET, &ip4_used);
- if (ip4_carrier_wanted) {
- /* If IPv4 wants a carrier and cannot fail, the whole connection
- * requires a carrier regardless of the IPv6 method.
- */
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- if (s_ip4 && !nm_setting_ip_config_get_may_fail(s_ip4))
- return TRUE;
- }
-
- ip6_carrier_wanted = connection_ip_method_requires_carrier(connection, AF_INET6, &ip6_used);
- if (ip6_carrier_wanted) {
- /* If IPv6 wants a carrier and cannot fail, the whole connection
- * requires a carrier regardless of the IPv4 method.
- */
- s_ip6 = nm_connection_get_setting_ip6_config(connection);
- if (s_ip6 && !nm_setting_ip_config_get_may_fail(s_ip6))
- return TRUE;
- }
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMNDiscDHCPLevel mode;
- /* If an IP version wants a carrier and the other IP version isn't
- * used, the connection requires carrier since it will just fail without one.
- */
- if (ip4_carrier_wanted && !ip6_used)
- return TRUE;
- if (ip6_carrier_wanted && !ip4_used)
- return TRUE;
+ g_return_val_if_fail(priv->dhcp_data_6.client != NULL, FALSE);
- /* If both want a carrier, the whole connection wants a carrier */
- return ip4_carrier_wanted && ip6_carrier_wanted;
-}
+ _LOGI(LOGD_DHCP6, "DHCPv6 lease renewal requested");
-static gboolean
-have_any_ready_slaves(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- SlaveInfo * info;
- CList * iter;
+ /* Terminate old DHCP instance and release the old lease */
+ mode = priv->dhcp6.mode;
+ dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release);
+ priv->dhcp6.mode = mode;
- /* Any enslaved slave is "ready" in the generic case as it's
- * at least >= NM_DEVCIE_STATE_IP_CONFIG and has had Layer 2
- * properties set up.
- */
- c_list_for_each (iter, &priv->slaves) {
- info = c_list_entry(iter, SlaveInfo, lst_slave);
- if (NM_DEVICE_GET_PRIVATE(info->slave)->is_enslaved)
- return TRUE;
- }
- return FALSE;
+ /* Start DHCP again on the interface */
+ return dhcp6_start(self, FALSE);
}
/*****************************************************************************/
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
/* DHCPv6 stuff */
static void
@@ -10035,6 +10140,8 @@ nm_device_dhcp6_renew(NMDevice *self, gboolean release)
}
/*****************************************************************************/
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
/*
* Called on the requesting interface when a subnet can't be obtained
@@ -10049,7 +10156,7 @@ nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes)
if (priv->dhcp_data_6.client) {
_LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes);
- nm_device_dhcp6_renew(self, FALSE);
+ nm_device_dhcp_renew(self, AF_INET6, FALSE);
} else {
_LOGI(LOGD_IP6, "ipv6-pd: device doesn't use DHCPv6, can't request prefixes");
}
@@ -10068,25 +10175,24 @@ nm_device_needs_ip6_subnet(NMDevice *self)
void
nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMPlatformIP6Address address = *subnet;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMPlatformIP6Address address;
- if (!applied_config_get_current(&priv->ac_ip6_config))
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
+ l3cd = nm_device_create_l3_config_data(self);
/* Assign a ::1 address in the subnet for us. */
+ address = *subnet;
address.address.s6_addr32[3] |= htonl(1);
- applied_config_add_address(&priv->ac_ip6_config, NM_PLATFORM_IP_ADDRESS_CAST(&address));
+
+ nm_l3_config_data_add_address_6(l3cd, &address);
_LOGD(LOGD_IP6,
- "ipv6-pd: using %s address (preferred for %u seconds)",
- _nm_utils_inet6_ntop(&address.address, sbuf),
- subnet->preferred);
+ "ipv6-pd: using %s",
+ nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)));
- /* This also updates the ndisc if there are actual changes. */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing");
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_PD_6, l3cd);
+ _dev_l3_cfg_commit(self);
}
/*
@@ -10096,41 +10202,47 @@ nm_device_use_ip6_subnet(NMDevice *self, const NMPlatformIP6Address *subnet)
void
nm_device_copy_ip6_dns_config(NMDevice *self, NMDevice *from_device)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP6Config * from_config = NULL;
- guint i, len;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate * priv_src;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ const NML3ConfigData * l3cd_src;
- if (applied_config_get_current(&priv->ac_ip6_config)) {
- applied_config_reset_nameservers(&priv->ac_ip6_config);
- applied_config_reset_searches(&priv->ac_ip6_config);
+ /* FIXME(l3fcg): this entire code an approach seems flawed. It's flawed, because the
+ * very next RA will reset the changes. */
+
+ if (priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d) {
+ l3cd = nm_l3_config_data_new_clone(priv->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d, 0);
+ nm_l3_config_data_clear_nameservers(l3cd, AF_INET6);
+ nm_l3_config_data_clear_searches(l3cd, AF_INET6);
} else
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
+ l3cd = nm_device_create_l3_config_data(self);
- if (from_device)
- from_config = nm_device_get_ip6_config(from_device);
- if (!from_config)
- return;
+ priv_src = NM_DEVICE_GET_PRIVATE(from_device);
+ l3cd_src = priv_src->l3cds[L3_CONFIG_DATA_TYPE_AC_6].d;
+ if (l3cd_src) {
+ const char *const * strvarr;
+ const struct in6_addr *const *addrs;
+ guint n;
+ guint i;
- len = nm_ip6_config_get_num_nameservers(from_config);
- for (i = 0; i < len; i++) {
- applied_config_add_nameserver(
- &priv->ac_ip6_config,
- (const NMIPAddr *) nm_ip6_config_get_nameserver(from_config, i));
- }
+ addrs = nm_l3_config_data_get_nameservers(l3cd_src, AF_INET6, &n);
+ for (i = 0; i < n; i++)
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, addrs[i]);
- len = nm_ip6_config_get_num_searches(from_config);
- for (i = 0; i < len; i++) {
- applied_config_add_search(&priv->ac_ip6_config, nm_ip6_config_get_search(from_config, i));
+ strvarr = nm_l3_config_data_get_searches(l3cd_src, AF_INET6, &n);
+ for (i = 0; i < n; i++)
+ nm_l3_config_data_add_search(l3cd, AF_INET6, strvarr[i]);
}
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing");
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, l3cd);
+
+ _dev_l3_cfg_commit(self);
}
/*****************************************************************************/
static void
-linklocal6_failed(NMDevice *self)
+_dev_ll6_failed(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -10139,17 +10251,18 @@ linklocal6_failed(NMDevice *self)
}
static gboolean
-linklocal6_timeout_cb(gpointer user_data)
+_dev_ll6_timeout_cb(gpointer user_data)
{
NMDevice *self = user_data;
_LOGD(LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout");
- linklocal6_failed(self);
+ _dev_ll6_failed(self);
return G_SOURCE_REMOVE;
}
-static void
-linklocal6_check_complete(NMDevice *self)
+//XXX
+_nm_unused static void
+_dev_ll6_check_complete(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
NMConnection * connection;
@@ -10160,18 +10273,18 @@ linklocal6_check_complete(NMDevice *self)
return;
}
- if (!priv->ext_ip6_config_captured
- || !nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
- /* we don't have a non-tentative link local address yet. Wait longer. */
- return;
- }
+ //XXX if ( !priv->ext_ip6_config_captured
+ //XXX || !nm_ip6_config_find_first_address (priv->ext_ip6_config_captured,
+ //XXX NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+ //XXX | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
+ //XXX /* we don't have a non-tentative link local address yet. Wait longer. */
+ //XXX return;
+ //XXX }
nm_clear_g_source(&priv->linklocal6_timeout_id);
connection = nm_device_get_applied_connection(self);
- g_assert(connection);
+ g_return_if_fail(connection);
method = nm_device_get_effective_ip_config_method(self, AF_INET6);
@@ -10182,14 +10295,14 @@ linklocal6_check_complete(NMDevice *self)
if (NM_IN_STRSET(method,
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NM_SETTING_IP6_CONFIG_METHOD_SHARED))
- addrconf6_start_with_link_ready(self);
+ _dev_ac6_start(self);
else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
- if (!dhcp6_start_with_link_ready(self, connection)) {
+ if (!_dev_dhcpx_start(self, AF_INET6)) {
/* Time out IPv6 instead of failing the entire activation */
nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
}
} else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL))
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+ nm_device_activate_schedule_ip_config_result(self, AF_INET6);
else
g_return_if_fail(FALSE);
}
@@ -10208,17 +10321,18 @@ check_and_add_ipv6ll_addr(NMDevice *self)
if (!priv->ipv6ll_handle)
return;
- if (priv->ext_ip6_config_captured
- && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) {
- /* Already have an LL address, nothing to do */
- return;
- }
+ //XXX if ( priv->ext_ip6_config_captured
+ //XXX && nm_ip6_config_find_first_address (priv->ext_ip6_config_captured,
+ //XXX NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+ //XXX | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL
+ //XXX | NM_PLATFORM_MATCH_WITH_ADDRSTATE_TENTATIVE)) {
+ //XXX /* Already have an LL address, nothing to do */
+ //XXX return;
+ //XXX }
priv->ipv6ll_has = FALSE;
memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr));
+ _dev_l3_set_l3cd_ll_6(self);
memset(&lladdr, 0, sizeof(lladdr));
lladdr.s6_addr16[0] = htons(0xfe80);
@@ -10242,7 +10356,7 @@ check_and_add_ipv6ll_addr(NMDevice *self)
&error)) {
_LOGW(LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
g_clear_error(&error);
- linklocal6_failed(self);
+ _dev_ll6_failed(self);
return;
}
addr_type = "stable-privacy";
@@ -10253,7 +10367,7 @@ check_and_add_ipv6ll_addr(NMDevice *self)
/* We already started and attempt to add a LL address. For the EUI-64
* mode we can't pick a new one, we'll just fail. */
_LOGW(LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address");
- linklocal6_failed(self);
+ _dev_ll6_failed(self);
return;
}
@@ -10271,21 +10385,36 @@ check_and_add_ipv6ll_addr(NMDevice *self)
_nm_utils_inet6_ntop(&lladdr, sbuf));
priv->ipv6ll_has = TRUE;
priv->ipv6ll_addr = lladdr;
- ip_config_merge_and_apply(self, AF_INET6, TRUE);
+ _dev_l3_cfg_commit(self);
}
static gboolean
-linklocal6_start(NMDevice *self)
+_dev_ll6_start(NMDevice *self, struct in6_addr *out_ll_addr)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ int ifindex;
- nm_clear_g_source(&priv->linklocal6_timeout_id);
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex > 0) {
+ const NMPObject *plobj;
+ NMDedupMultiIter iter;
+ NMPLookup lookup;
+
+ nm_platform_iter_obj_for_each (
+ &iter,
+ nm_device_get_platform(self),
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex),
+ &plobj) {
+ if (nm_platform_ip6_address_match(NMP_OBJECT_CAST_IP6_ADDRESS(plobj),
+ NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
+ | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL)) {
+ NM_SET_OUT(out_ll_addr, NMP_OBJECT_CAST_IP6_ADDRESS(plobj)->address);
+ return TRUE;
+ }
+ }
+ }
- if (priv->ext_ip6_config_captured
- && nm_ip6_config_find_first_address(priv->ext_ip6_config_captured,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL))
- return TRUE;
+ nm_clear_g_source(&priv->linklocal6_timeout_id);
_LOGD(LOGD_DEVICE,
"linklocal6: starting IPv6 with method '%s', but the device has no link-local addresses "
@@ -10299,7 +10428,7 @@ linklocal6_start(NMDevice *self)
* FIXME: use dad/retrans sysctl values if they are higher than a minimum time.
* (rh #1101809)
*/
- priv->linklocal6_timeout_id = g_timeout_add_seconds(15, linklocal6_timeout_cb, self);
+ priv->linklocal6_timeout_id = g_timeout_add_seconds(15, _dev_ll6_timeout_cb, self);
return FALSE;
}
@@ -10463,13 +10592,16 @@ set_platform_mtu(NMDevice *self, guint32 mtu)
}
static void
-_commit_mtu(NMDevice *self, const NMIP4Config *config)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE;
- guint32 ip6_mtu, ip6_mtu_orig;
- guint32 mtu_desired, mtu_desired_orig;
- guint32 mtu_plat;
+_commit_mtu(NMDevice *self)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDeviceMtuSource source = NM_DEVICE_MTU_SOURCE_NONE;
+ const NML3ConfigData *l3cd;
+ guint32 ip6_mtu_orig;
+ guint32 ip6_mtu;
+ guint32 mtu_desired_orig;
+ guint32 mtu_desired;
+ guint32 mtu_plat;
struct {
gboolean initialized;
guint32 value;
@@ -10477,7 +10609,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
0,
};
int ifindex;
- char sbuf[64], sbuf1[64], sbuf2[64];
+ char sbuf[64];
+ char sbuf1[64];
+ char sbuf2[64];
gboolean success = TRUE;
ifindex = nm_device_get_ip_ifindex(self);
@@ -10491,8 +10625,11 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
return;
}
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, FALSE);
+
{
- guint32 mtu = 0;
+ guint32 mtu = 0;
+ guint32 mtu2;
gboolean force = FALSE;
/* We take the MTU from various sources: (in order of increasing
@@ -10519,9 +10656,9 @@ _commit_mtu(NMDevice *self, const NMIP4Config *config)
if (NM_DEVICE_GET_CLASS(self)->get_configured_mtu)
mtu = NM_DEVICE_GET_CLASS(self)->get_configured_mtu(self, &source, &force);
- if (config && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
- && nm_ip4_config_get_mtu(config)) {
- mtu = nm_ip4_config_get_mtu(config);
+ if (l3cd && !force && source < NM_DEVICE_MTU_SOURCE_IP_CONFIG
+ && (mtu2 = nm_l3_config_data_get_mtu(l3cd)) > 0) {
+ mtu = mtu2;
source = NM_DEVICE_MTU_SOURCE_IP_CONFIG;
}
@@ -10704,244 +10841,148 @@ nm_device_commit_mtu(NMDevice *self)
state = nm_device_get_state(self);
if (state >= NM_DEVICE_STATE_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) {
_LOGT(LOGD_DEVICE, "mtu: commit-mtu...");
- _commit_mtu(self, NM_DEVICE_GET_PRIVATE(self)->ip_config_4);
+ _commit_mtu(self);
} else
_LOGT(LOGD_DEVICE,
"mtu: commit-mtu... skip due to state %s",
nm_device_state_to_str(state));
}
+/*****************************************************************************/
+
static void
-ndisc_config_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, NMDevice *self)
+_dev_ac6_ndisc_config_changed(NMNDisc * ndisc,
+ const NMNDiscData *rdata,
+ guint changed_i,
+ NMDevice * self)
{
- NMNDiscConfigMap changed = changed_int;
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- guint i;
-
- g_return_if_fail(priv->act_request.obj);
-
- if (!applied_config_get_current(&priv->ac_ip6_config))
- applied_config_init_new(&priv->ac_ip6_config, self, AF_INET6);
-
- if (changed & NM_NDISC_CONFIG_ADDRESSES) {
- guint8 plen;
- guint32 ifa_flags;
-
- /* Check, whether kernel is recent enough to help user space handling RA.
- * If it's not supported, we have no ipv6-privacy and must add autoconf
- * addresses as /128. The reason for the /128 is to prevent the kernel
- * from adding a prefix route for this address. */
- ifa_flags = 0;
- if (nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) {
- ifa_flags |= IFA_F_NOPREFIXROUTE;
- if (NM_IN_SET(priv->ndisc_use_tempaddr,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
- NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR))
- ifa_flags |= IFA_F_MANAGETEMPADDR;
- plen = 64;
- } else
- plen = 128;
-
- nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.orig,
- rdata->addresses,
- rdata->addresses_n,
- plen,
- ifa_flags);
- if (priv->ac_ip6_config.current) {
- nm_ip6_config_reset_addresses_ndisc((NMIP6Config *) priv->ac_ip6_config.current,
- rdata->addresses,
- rdata->addresses_n,
- plen,
- ifa_flags);
- }
- }
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ int ifindex;
- if (NM_FLAGS_ANY(changed, NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_GATEWAYS)) {
- nm_ip6_config_reset_routes_ndisc(
- (NMIP6Config *) priv->ac_ip6_config.orig,
- rdata->gateways,
- rdata->gateways_n,
- rdata->routes,
- rdata->routes_n,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6),
- nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF));
- if (priv->ac_ip6_config.current) {
- nm_ip6_config_reset_routes_ndisc(
- (NMIP6Config *) priv->ac_ip6_config.current,
- rdata->gateways,
- rdata->gateways_n,
- rdata->routes,
- rdata->routes_n,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6),
- nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF));
- }
- }
-
- if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
- /* Rebuild DNS server list from neighbor discovery cache. */
- applied_config_reset_nameservers(&priv->ac_ip6_config);
-
- for (i = 0; i < rdata->dns_servers_n; i++)
- applied_config_add_nameserver(&priv->ac_ip6_config,
- (const NMIPAddr *) &rdata->dns_servers[i].address);
- }
+ ifindex = nm_device_get_ip_ifindex(self);
+ if (ifindex <= 0)
+ g_return_if_reached();
- if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) {
- /* Rebuild domain list from neighbor discovery cache. */
- applied_config_reset_searches(&priv->ac_ip6_config);
+ l3cd = nm_ndisc_data_to_l3cd(
+ nm_device_get_multi_index(self),
+ ifindex,
+ rdata,
+ priv->ac6_ip6_privacy,
+ nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_RTA_PREF),
+ nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS));
- for (i = 0; i < rdata->dns_domains_n; i++)
- applied_config_add_search(&priv->ac_ip6_config, rdata->dns_domains[i].domain);
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, l3cd);
- if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, TRUE);
+ _dev_dhcp6_set_dhcp_level(self, rdata->dhcp_level);
- priv->dhcp6.mode = rdata->dhcp_level;
- if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) {
- _LOGD(LOGD_DEVICE | LOGD_DHCP6,
- "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6"
- " as requested by IPv6 router...");
- if (!dhcp6_start(self, FALSE)) {
- if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
- return;
- }
- }
- }
- }
+ _dev_l3_cfg_commit(self);
+}
- if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
- nm_platform_sysctl_ip_conf_set_ipv6_hop_limit_safe(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->hop_limit);
+static void
+_dev_ac6_handle_timeout(NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (changed & NM_NDISC_CONFIG_REACHABLE_TIME) {
- nm_platform_sysctl_ip_neigh_set_ipv6_reachable_time(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->reachable_time_ms);
- }
+ _LOGD(LOGD_IP6, "ac6: timeout for autoconf (IPv6 router advertisement) reached");
- if (changed & NM_NDISC_CONFIG_RETRANS_TIMER) {
- nm_platform_sysctl_ip_neigh_set_ipv6_retrans_time(nm_device_get_platform(self),
- nm_device_get_ip_iface(self),
- rdata->retrans_timer_ms);
- }
+ nm_clear_g_source_inst(&priv->ac6_ndisc_grace_source);
+ priv->ac6_ndisc_grace_pending = FALSE;
+ _set_ip_state_check(self, AF_INET6);
+}
- if (changed & NM_NDISC_CONFIG_MTU) {
- if (priv->ip6_mtu != rdata->mtu) {
- _LOGD(LOGD_DEVICE, "mtu: set IPv6 MTU to %u", (guint) rdata->mtu);
- priv->ip6_mtu = rdata->mtu;
- }
- }
+static void
+_dev_ac6_ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self)
+{
+ _dev_ac6_handle_timeout(self);
+}
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
+static gboolean
+_dev_ac6_grace_period_expired(gpointer user_data)
+{
+ _dev_ac6_handle_timeout(user_data);
+ return G_SOURCE_REMOVE;
}
-static void
-ndisc_ra_timeout(NMNDisc *ndisc, NMDevice *self)
+static gboolean
+_dev_ac6_grace_period_start(NMDevice *self, guint32 timeout_sec, gboolean force_restart)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- /* We don't want to stop listening for router advertisements completely,
- * but instead let device activation continue activating. If an RA
- * shows up later, we'll use it as long as the device is not disconnected.
+ /* In any other case (expired lease, assumed connection, etc.),
+ * wait for some time before failing the IP method.
*/
-
- _LOGD(LOGD_IP6, "timed out waiting for IPv6 router advertisement");
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) {
- /* If RA is our only source of addressing information and we don't
- * ever receive one, then time out IPv6. But if there is other
- * IPv6 configuration, like manual IPv6 addresses or external IPv6
- * config, consider that sufficient for IPv6 success.
- *
- * FIXME: it doesn't seem correct to determine this based on which
- * addresses we find inside priv->ip_config_6.
- */
- if (priv->ip_config_6
- && nm_ip6_config_find_first_address(priv->ip_config_6,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY))
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- else
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
+ if (!force_restart && priv->ac6_ndisc_grace_pending) {
+ /* already pending. */
+ return FALSE;
}
-}
-static void
-addrconf6_start_with_link_ready(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMUtilsIPv6IfaceId iid;
+ /* Start a grace period equal to the RA timeout multiplied
+ * by a constant factor. */
- g_assert(priv->ndisc);
+ nm_clear_g_source_inst(&priv->ac6_ndisc_grace_source);
- if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
- _LOGD(LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
- nm_ndisc_set_iid(priv->ndisc, iid);
- } else {
- /* Don't abort the addrconf at this point -- if ndisc needs the iid
- * it will notice this itself. */
- _LOGI(LOGD_IP6, "addrconf6: no interface identifier; IPv6 address creation may fail");
+ if (timeout_sec == 0) {
+ priv->ac6_ndisc_grace_pending = FALSE;
+ return FALSE;
}
- /* Apply any manual configuration before starting RA */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed to apply manual IPv6 configuration");
+ nm_assert(timeout_sec <= G_MAXINT32);
- if (nm_ndisc_get_node_type(priv->ndisc) == NM_NDISC_NODE_TYPE_ROUTER) {
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1");
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- priv->needs_ip6_subnet = TRUE;
- g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0);
- }
+ if (timeout_sec == NM_RA_TIMEOUT_INFINITY)
+ _LOGD(LOGD_IP6, "ac6: grace period is infinity");
+ else {
+ guint timeout_msec;
- priv->ndisc_changed_id = g_signal_connect(priv->ndisc,
- NM_NDISC_CONFIG_RECEIVED,
- G_CALLBACK(ndisc_config_changed),
- self);
- priv->ndisc_timeout_id = g_signal_connect(priv->ndisc,
- NM_NDISC_RA_TIMEOUT_SIGNAL,
- G_CALLBACK(ndisc_ra_timeout),
- self);
+ _LOGD(LOGD_IP6, "ac6: grace period is %u seconds", timeout_sec);
- ndisc_set_router_config(priv->ndisc, self);
- nm_ndisc_start(priv->ndisc);
- priv->ndisc_started = TRUE;
- return;
+ if (timeout_sec < G_MAXUINT / (GRACE_PERIOD_MULTIPLIER * 1000u))
+ timeout_msec = timeout_sec * (GRACE_PERIOD_MULTIPLIER * 1000u);
+ else
+ timeout_msec = G_MAXUINT;
+
+ priv->ac6_ndisc_grace_source =
+ nm_g_source_attach(nm_g_timeout_source_new(timeout_msec,
+ G_PRIORITY_DEFAULT,
+ _dev_ac6_grace_period_expired,
+ self,
+ NULL),
+ NULL);
+ }
+
+ priv->ac6_ndisc_grace_pending = TRUE;
+ return TRUE;
}
static gboolean
-addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
+_dev_ac6_start(NMDevice *self)
{
NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMSettingIP6Config *s_ip;
NMConnection * connection;
- NMSettingIP6Config *s_ip6 = NULL;
- GError * error = NULL;
- NMUtilsStableType stable_type;
- const char * stable_id;
- NMNDiscNodeType node_type;
- int max_addresses;
- int router_solicitations;
- int router_solicitation_interval;
- guint32 ra_timeout;
- guint32 default_ra_timeout;
+ gs_free_error GError *error = NULL;
+ NMUtilsStableType stable_type;
+ NMNDiscNodeType node_type;
+ const char * stable_id;
+ int max_addresses;
+ int router_solicitations;
+ int router_solicitation_interval;
+ guint32 ra_timeout;
+ guint32 default_ra_timeout;
+ NMUtilsIPv6IfaceId iid;
connection = nm_device_get_applied_connection(self);
- g_assert(connection);
-
- nm_assert(!applied_config_get_current(&priv->ac_ip6_config));
- applied_config_clear(&priv->ac_ip6_config);
+ nm_assert(connection);
+ s_ip = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection));
+ nm_assert(s_ip);
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
+ priv->ac6_ndisc_started = TRUE;
- s_ip6 = NM_SETTING_IP6_CONFIG(nm_connection_get_setting_ip6_config(connection));
- g_assert(s_ip6);
+ if (!_dev_ll6_start(self, NULL)) {
+ /* wait for the LL address to show up */
+ _dev_ac6_grace_period_start(self, 30, TRUE);
+ return TRUE;
+ }
if (nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET6),
NM_SETTING_IP4_CONFIG_METHOD_SHARED))
@@ -10964,28 +11005,30 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
ra_timeout = default_ra_timeout;
}
- stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
- priv->ndisc = nm_lndp_ndisc_new(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- nm_device_get_ip_iface(self),
- stable_type,
- stable_id,
- nm_setting_ip6_config_get_addr_gen_mode(s_ip6),
- node_type,
- max_addresses,
- router_solicitations,
- router_solicitation_interval,
- ra_timeout,
- &error);
- if (!priv->ndisc) {
+ _dev_ac6_grace_period_start(self, ra_timeout, TRUE);
+
+ stable_id = _prop_get_connection_stable_id(self, connection, &stable_type);
+
+ priv->ac6_ndisc = nm_lndp_ndisc_new(nm_device_get_platform(self),
+ nm_device_get_ip_ifindex(self),
+ nm_device_get_ip_iface(self),
+ stable_type,
+ stable_id,
+ nm_setting_ip6_config_get_addr_gen_mode(s_ip),
+ node_type,
+ max_addresses,
+ router_solicitations,
+ router_solicitation_interval,
+ ra_timeout,
+ &error);
+ if (!priv->ac6_ndisc) {
_LOGE(LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);
- g_error_free(error);
return FALSE;
}
- priv->ndisc_use_tempaddr = use_tempaddr;
+ priv->ac6_ip6_privacy = _prop_get_ipv6_ip6_privacy(self);
- if (NM_IN_SET(use_tempaddr,
+ if (NM_IN_SET(priv->ac6_ip6_privacy,
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
&& !nm_platform_kernel_support_get(NM_PLATFORM_KERNEL_SUPPORT_TYPE_EXTENDED_IFA_FLAGS)) {
@@ -10994,32 +11037,58 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
"IPv6 private addresses. This feature is not available");
}
- /* ensure link local is ready... */
- if (!linklocal6_start(self)) {
- /* wait for the LL address to show up */
- return TRUE;
+ if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
+ _LOGD(LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
+ nm_ndisc_set_iid(priv->ac6_ndisc, iid);
+ } else {
+ /* Don't abort the addrconf at this point -- if ndisc needs the iid
+ * it will notice this itself. */
+ _LOGD(LOGD_IP6, "addrconf6: no interface identifier; IPv6 address creation may fail");
+ }
+
+ _dev_l3_cfg_commit(self);
+
+ if (nm_ndisc_get_node_type(priv->ac6_ndisc) == NM_NDISC_NODE_TYPE_ROUTER) {
+ nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1");
+ nm_device_activate_schedule_ip_config_result(self, AF_INET6);
+ priv->needs_ip6_subnet = TRUE;
+ g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0);
}
- /* already have the LL address; kick off neighbor discovery */
- addrconf6_start_with_link_ready(self);
+ priv->ac6_ndisc_changed_id = g_signal_connect(priv->ac6_ndisc,
+ NM_NDISC_CONFIG_RECEIVED,
+ G_CALLBACK(_dev_ac6_ndisc_config_changed),
+ self);
+ priv->ac6_ndisc_timeout_id = g_signal_connect(priv->ac6_ndisc,
+ NM_NDISC_RA_TIMEOUT_SIGNAL,
+ G_CALLBACK(_dev_ac6_ndisc_ra_timeout),
+ self);
+
+ _dev_ac6_ndisc_set_router_config(self);
+
+ nm_ndisc_start(priv->ac6_ndisc);
+
+ priv->ac6_ndisc_started = TRUE;
+
return TRUE;
}
static void
-addrconf6_cleanup(NMDevice *self)
+_dev_ac6_cleanup(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- priv->ndisc_started = FALSE;
- nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_changed_id);
- nm_clear_g_signal_handler(priv->ndisc, &priv->ndisc_timeout_id);
+ priv->ac6_ndisc_started = FALSE;
+ priv->ac6_ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
- applied_config_clear(&priv->ac_ip6_config);
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- if (priv->ndisc) {
- nm_ndisc_stop(priv->ndisc);
- g_clear_object(&priv->ndisc);
+ nm_clear_g_signal_handler(priv->ac6_ndisc, &priv->ac6_ndisc_changed_id);
+ nm_clear_g_signal_handler(priv->ac6_ndisc, &priv->ac6_ndisc_timeout_id);
+
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, NULL);
+
+ if (priv->ac6_ndisc) {
+ nm_ndisc_stop(priv->ac6_ndisc);
+ g_clear_object(&priv->ac6_ndisc);
}
}
@@ -11141,10 +11210,10 @@ ip_requires_slaves(NMDevice *self, int addr_family)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * self,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * self,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -11193,52 +11262,34 @@ act_stage3_ip_config_start(NMDevice * self,
NM_SETTING_IP4_CONFIG_METHOD_AUTO,
NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
NMSettingIPConfig *s_ip4;
- NMIP4Config ** configs, *config;
guint num_addresses;
+ /* FIXME(l3cfg) */
s_ip4 = nm_connection_get_setting_ip4_config(connection);
g_return_val_if_fail(s_ip4, NM_ACT_STAGE_RETURN_FAILURE);
num_addresses = nm_setting_ip_config_get_num_addresses(s_ip4);
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
- ret = dhcp4_start(self);
- if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
+ if (!_dev_dhcpx_start(self, AF_INET)) {
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
- return ret;
+ return NM_ACT_STAGE_RETURN_FAILURE;
}
- } else {
+ } else
g_return_val_if_fail(num_addresses != 0, NM_ACT_STAGE_RETURN_FAILURE);
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
- }
-
- if (num_addresses) {
- config = nm_device_ip4_config_new(self);
- nm_ip4_config_merge_setting(config,
- nm_connection_get_setting_ip4_config(connection),
- NM_SETTING_CONNECTION_MDNS_DEFAULT,
- NM_SETTING_CONNECTION_LLMNR_DEFAULT,
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
- configs = g_new0(NMIP4Config *, 2);
- configs[0] = config;
- ipv4_dad_start(self, configs, ipv4_manual_method_apply);
- }
+ ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) {
- ret = ipv4ll_start(self);
+ ret = _dev_ll4_start(self);
if (ret == NM_ACT_STAGE_RETURN_FAILURE)
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED);
} else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
- if (out_config) {
- *out_config = shared4_new_config(self, connection);
- if (*out_config) {
- priv->dnsmasq_manager = nm_dnsmasq_manager_new(nm_device_get_ip_iface(self));
- ret = NM_ACT_STAGE_RETURN_SUCCESS;
- } else {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- ret = NM_ACT_STAGE_RETURN_FAILURE;
- }
- } else
- g_return_val_if_reached(NM_ACT_STAGE_RETURN_FAILURE);
+ gs_free_error GError *error = NULL;
+
+ if (!_dev_shared4_start(self, &error)) {
+ _LOGW(LOGD_SHARING, "Activation: start sharing failed: %s", error->message);
+ NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
+ return NM_ACT_STAGE_RETURN_FAILURE;
+ }
+ ret = NM_ACT_STAGE_RETURN_SUCCESS;
} else if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED))
ret = NM_ACT_STAGE_RETURN_SUCCESS;
else
@@ -11246,10 +11297,7 @@ act_stage3_ip_config_start(NMDevice * self,
return ret;
} else {
- NMSettingIP6ConfigPrivacy ip6_privacy = NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
- const char * ip6_privacy_str = "0";
- NMPlatform * platform;
- int ifindex;
+ int ifindex;
if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DISABLED)) {
nm_device_sysctl_ip_conf_set(self, AF_INET6, "disable_ipv6", "1");
@@ -11267,15 +11315,12 @@ act_stage3_ip_config_start(NMDevice * self,
* slave should not depend on the previous state. Flush
* addresses and routes on activation.
*/
- ifindex = nm_device_get_ip_ifindex(self);
- platform = nm_device_get_platform(self);
-
+ ifindex = nm_device_get_ip_ifindex(self);
if (ifindex > 0) {
- gs_unref_object NMIP6Config *config = nm_device_ip6_config_new(self);
-
- nm_platform_ip_route_flush(platform, AF_INET6, ifindex);
- nm_platform_ip_address_flush(platform, AF_INET6, ifindex);
- nm_device_set_ip_config(self, AF_INET6, (NMIPConfig *) config, FALSE, NULL);
+ nm_platform_ip_route_flush(nm_device_get_platform(self), AF_INET6, ifindex);
+ nm_platform_ip_address_flush(nm_device_get_platform(self),
+ AF_INET6,
+ ifindex);
}
} else {
gboolean ipv6ll_handle_old = priv->ipv6ll_handle;
@@ -11297,7 +11342,7 @@ act_stage3_ip_config_start(NMDevice * self,
* expose any ipv6 sysctls or allow presence of any addresses on the interface,
* including LL, which * would make it impossible to autoconfigure MTU to a
* correct value. */
- _commit_mtu(self, priv->ip_config_4);
+ _commit_mtu(self);
/* Any method past this point requires an IPv6LL address. Use NM-controlled
* IPv6LL if this is not an assumed connection, since assumed connections
@@ -11311,33 +11356,30 @@ act_stage3_ip_config_start(NMDevice * self,
set_disable_ipv6(self, "0");
/* Synchronize external IPv6 configuration with kernel, since
- * linklocal6_start() uses the information there to determine if we can
+ * _dev_ll6_start() uses the information there to determine if we can
* proceed with the selected method (SLAAC, DHCP, link-local).
*/
nm_platform_process_events(nm_device_get_platform(self));
- g_clear_object(&priv->ext_ip6_config_captured);
- priv->ext_ip6_config_captured =
- nm_ip6_config_capture(nm_device_get_multi_index(self),
- nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
-
- ip6_privacy = _prop_get_ipv6_ip6_privacy(self);
+ //XXX g_clear_object (&priv->ext_ip6_config_captured);
+ //XXX priv->ext_ip6_config_captured = nm_ip6_config_capture (nm_device_get_multi_index (self),
+ //XXX nm_device_get_platform (self),
+ //XXX nm_device_get_ip_ifindex (self),
+ //XXX NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
if (NM_IN_STRSET(method,
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
- if (!addrconf6_start(self, ip6_privacy)) {
+ if (!_dev_ac6_start(self)) {
/* IPv6 might be disabled; allow IPv4 to proceed */
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
} else
ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
- ret =
- linklocal6_start(self) ? NM_ACT_STAGE_RETURN_SUCCESS : NM_ACT_STAGE_RETURN_POSTPONE;
+ ret = _dev_ll6_start(self, NULL) ? NM_ACT_STAGE_RETURN_SUCCESS
+ : NM_ACT_STAGE_RETURN_POSTPONE;
} else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED;
- if (!dhcp6_start(self, TRUE)) {
+ if (!_dev_dhcpx_start(self, AF_INET6)) {
/* IPv6 might be disabled; allow IPv4 to proceed */
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
} else
@@ -11347,23 +11389,6 @@ act_stage3_ip_config_start(NMDevice * self,
else
_LOGW(LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method);
- if (ret != NM_ACT_STAGE_RETURN_FAILURE
- && !nm_device_sys_iface_state_is_external_or_assume(self)) {
- switch (ip6_privacy) {
- case NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN:
- case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED:
- ip6_privacy_str = "0";
- break;
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR:
- ip6_privacy_str = "1";
- break;
- case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR:
- ip6_privacy_str = "2";
- break;
- }
- nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", ip6_privacy_str);
- }
-
return ret;
}
}
@@ -11371,13 +11396,13 @@ act_stage3_ip_config_start(NMDevice * self,
gboolean
nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMActStageReturn ret;
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
- gs_unref_object NMIPConfig *ip_config = NULL;
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMActStageReturn ret;
+ NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
- g_assert(priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_WAIT);
+ g_return_val_if_fail(priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_WAIT, FALSE);
if (nm_device_sys_iface_state_is_external(self)) {
_set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
@@ -11389,22 +11414,13 @@ nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family)
ret = NM_DEVICE_GET_CLASS(self)->act_stage3_ip_config_start(self,
addr_family,
- (gpointer *) &ip_config,
+ &l3cd,
&failure_reason);
switch (ret) {
case NM_ACT_STAGE_RETURN_SUCCESS:
- if (!IS_IPv4) {
- /* Here we get a static IPv6 config, like for Shared where it's
- * autogenerated or from modems where it comes from ModemManager.
- */
- if (!ip_config)
- ip_config = nm_device_ip_config_new(self, addr_family);
- nm_assert(!applied_config_get_current(&priv->ac_ip6_config));
- applied_config_init(&priv->ac_ip6_config, ip_config);
- ip_config = NULL;
- }
- nm_device_activate_schedule_ip_config_result(self, addr_family, ip_config);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DEV_X(IS_IPv4), l3cd);
+ nm_device_activate_schedule_ip_config_result(self, addr_family);
break;
case NM_ACT_STAGE_RETURN_IP_DONE:
_set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
@@ -11461,8 +11477,7 @@ activate_stage3_ip_config_start(NMDevice *self)
&& !nm_device_activate_stage3_ip_start(self, AF_INET6))
return;
- /* Proxy */
- nm_device_set_proxy_config(self, NULL);
+ nm_device_set_proxy_config(self);
check_ip_state(self, TRUE, TRUE);
}
@@ -11654,8 +11669,66 @@ nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family)
addr_family);
}
+/*****************************************************************************/
+
+static const NML3ConfigData *
+_dev_shared4_new_l3cd(NMDevice *self, NMConnection *connection, NMPlatformIP4Address *out_addr4)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMSettingIPConfig * s_ip4;
+ NMPlatformIP4Address address = {
+ .addr_source = NM_IP_CONFIG_SOURCE_SHARED,
+ };
+
+ g_return_val_if_fail(self, NULL);
+ g_return_val_if_fail(connection, NULL);
+
+ s_ip4 = nm_connection_get_setting_ip4_config(connection);
+ if (s_ip4 && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
+ /* Use the first user-supplied address */
+ NMIPAddress *user = nm_setting_ip_config_get_address(s_ip4, 0);
+ in_addr_t a;
+
+ nm_ip_address_get_address_binary(user, &a);
+ nm_platform_ip4_address_set_addr(&address, a, nm_ip_address_get_prefix(user));
+ nm_clear_pointer(&priv->shared4_ip_handle, nm_netns_shared_ip_release);
+ } else {
+ if (!priv->shared4_ip_handle)
+ priv->shared4_ip_handle = nm_netns_shared_ip_reserve(nm_device_get_netns(self));
+ nm_platform_ip4_address_set_addr(&address, priv->shared4_ip_handle->addr, 24);
+ }
+
+ l3cd = nm_device_create_l3_config_data(self);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_SHARED);
+ nm_l3_config_data_add_address_4(l3cd, &address);
+
+ NM_SET_OUT(out_addr4, address);
+
+ return nm_l3_config_data_seal(g_steal_pointer(&l3cd));
+}
+
+static void
+_dev_shared4_cleanup(NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ if (priv->shared4_dnsmasq_manager) {
+ nm_clear_g_signal_handler(priv->shared4_dnsmasq_manager, &priv->shared4_dnsmasq_state_id);
+ nm_dnsmasq_manager_stop(priv->shared4_dnsmasq_manager);
+ g_clear_object(&priv->shared4_dnsmasq_manager);
+ }
+
+ if (priv->shared4_rules) {
+ nm_utils_share_rules_apply(priv->shared4_rules, FALSE);
+ nm_clear_pointer(&priv->shared4_rules, nm_utils_share_rules_free);
+ }
+
+ nm_clear_pointer(&priv->shared4_ip_handle, nm_netns_shared_ip_release);
+}
+
static gboolean
-share_init(NMDevice *self, GError **error)
+_dev_shared4_init(NMDevice *self, GError **error)
{
const char *const modules[] = {"ip_tables",
"iptable_nat",
@@ -11710,29 +11783,37 @@ share_init(NMDevice *self, GError **error)
return TRUE;
}
-static gboolean
-start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
+static void
+_dev_shared4_dnsmasq_state_changed_cb(NMDnsMasqManager *manager, guint status, gpointer user_data)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMActRequest * req;
- const NMPlatformIP4Address *ip4_addr = NULL;
- const char * ip_iface;
- GError * local = NULL;
- NMConnection * conn;
- NMSettingConnection * s_con;
- gboolean announce_android_metered;
- NMUtilsShareRules * share_rules;
-
- g_return_val_if_fail(config, FALSE);
+ NMDevice *self = NM_DEVICE(user_data);
- ip_iface = nm_device_get_ip_iface(self);
- if (!ip_iface) {
- g_set_error(error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, "device has no ip interface");
- return FALSE;
- }
+ if (status == NM_DNSMASQ_STATUS_DEAD)
+ nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
+}
- ip4_addr = nm_ip4_config_get_first_address(config);
- if (!ip4_addr || !ip4_addr->address) {
+static gboolean
+_dev_shared4_start(NMDevice *self, GError **error)
+{
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address ip4_addr;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NMActRequest * req;
+ const char * ip_iface;
+ GError * local = NULL;
+ NMConnection * conn;
+ NMSettingConnection * s_con;
+ gboolean announce_android_metered;
+ NMConnection * applied;
+
+ nm_assert(!priv->shared4_rules);
+ nm_assert(!priv->shared4_dnsmasq_manager);
+ nm_assert(priv->shared4_dnsmasq_state_id == 0);
+
+ applied = nm_device_get_applied_connection(self);
+
+ l3cd = _dev_shared4_new_l3cd(self, applied, &ip4_addr);
+ if (!l3cd) {
g_set_error(error,
NM_UTILS_ERROR,
NM_UTILS_ERROR_UNKNOWN,
@@ -11740,19 +11821,23 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
return FALSE;
}
- if (!share_init(self, error))
+ if (!_dev_shared4_init(self, error))
return FALSE;
+ ip_iface = nm_device_get_ip_iface(self);
+ g_return_val_if_fail(ip_iface, FALSE);
+
req = nm_device_get_act_request(self);
g_return_val_if_fail(req, FALSE);
- share_rules = nm_utils_share_rules_new();
+ priv->shared4_rules = nm_utils_share_rules_new();
- nm_utils_share_rules_add_all_rules(share_rules, ip_iface, ip4_addr->address, ip4_addr->plen);
+ nm_utils_share_rules_add_all_rules(priv->shared4_rules,
+ ip_iface,
+ ip4_addr.address,
+ ip4_addr.plen);
- nm_utils_share_rules_apply(share_rules, TRUE);
-
- nm_act_request_set_shared(req, share_rules);
+ nm_utils_share_rules_apply(priv->shared4_rules, TRUE);
conn = nm_act_request_get_applied_connection(req);
s_con = nm_connection_get_setting_connection(conn);
@@ -11777,8 +11862,10 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
break;
}
- if (!nm_dnsmasq_manager_start(priv->dnsmasq_manager,
- config,
+ priv->shared4_dnsmasq_manager = nm_dnsmasq_manager_new(nm_device_get_ip_iface(self));
+
+ if (!nm_dnsmasq_manager_start(priv->shared4_dnsmasq_manager,
+ l3cd,
announce_android_metered,
&local)) {
g_set_error(error,
@@ -11786,81 +11873,29 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error)
NM_UTILS_ERROR_UNKNOWN,
"could not start dnsmasq due to %s",
local->message);
- g_error_free(local);
- nm_act_request_set_shared(req, NULL);
+ g_clear_error(&local);
+ _dev_shared4_cleanup(self);
return FALSE;
}
- priv->dnsmasq_state_id = g_signal_connect(priv->dnsmasq_manager,
- NM_DNS_MASQ_MANAGER_STATE_CHANGED,
- G_CALLBACK(dnsmasq_state_changed_cb),
- self);
- return TRUE;
-}
+ priv->shared4_dnsmasq_state_id =
+ g_signal_connect(priv->shared4_dnsmasq_manager,
+ NM_DNS_MASQ_MANAGER_STATE_CHANGED,
+ G_CALLBACK(_dev_shared4_dnsmasq_state_changed_cb),
+ self);
-static void
-arp_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, l3cd);
- nm_clear_pointer(&priv->acd.announcing, nm_acd_manager_free);
-}
-
-void
-nm_device_arp_announce(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
- NMSettingIPConfig *s_ip4;
- guint num, i;
- const guint8 * hw_addr;
- size_t hw_addr_len = 0;
-
- arp_cleanup(self);
-
- hw_addr = nm_platform_link_get_address(nm_device_get_platform(self),
- nm_device_get_ip_ifindex(self),
- &hw_addr_len);
-
- if (!hw_addr || hw_addr_len != ETH_ALEN)
- return;
-
- /* We only care about manually-configured addresses; DHCP- and autoip-configured
- * ones should already have been seen on the network at this point.
- */
- connection = nm_device_get_applied_connection(self);
- if (!connection)
- return;
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
- if (!s_ip4)
- return;
- num = nm_setting_ip_config_get_num_addresses(s_ip4);
- if (num == 0)
- return;
-
- priv->acd.announcing =
- nm_acd_manager_new(nm_device_get_ip_ifindex(self), hw_addr, hw_addr_len, NULL, NULL);
-
- for (i = 0; i < num; i++) {
- NMIPAddress *ip = nm_setting_ip_config_get_address(s_ip4, i);
- in_addr_t addr;
-
- if (inet_pton(AF_INET, nm_ip_address_get_address(ip), &addr) == 1)
- nm_acd_manager_add_address(priv->acd.announcing, addr);
- else
- g_warn_if_reached();
- }
-
- nm_acd_manager_announce_addresses(priv->acd.announcing);
+ return TRUE;
}
static void
activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
{
+#if 0 //XXX
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
NMActRequest * req;
- const char * method;
int ip_ifindex;
int errsv;
gboolean do_announce = FALSE;
@@ -12021,6 +12056,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
_set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE);
check_ip_state(self, FALSE, TRUE);
}
+#endif
}
static void
@@ -12040,18 +12076,18 @@ activate_stage5_ip_config_result_6(NMDevice *self)
: activate_stage5_ip_config_result_6)
void
-nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family, NMIPConfig *config)
+nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family)
{
NMDevicePrivate *priv;
const int IS_IPv4 = NM_IS_IPv4(addr_family);
g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(!config || (IS_IPv4 && nm_ip_config_get_addr_family(config) == AF_INET));
+ g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6));
priv = NM_DEVICE_GET_PRIVATE(self);
if (IS_IPv4) {
- applied_config_init(&priv->dev_ip_config_4, config);
+ /* FIXME(l3cfg): surely there is something to do here? */
} else {
/* If IP had previously failed, move it back to NM_DEVICE_IP_STATE_CONF since we
* clearly now have configuration.
@@ -12076,73 +12112,6 @@ nm_device_activate_get_ip_state(NMDevice *self, int addr_family)
return NM_DEVICE_GET_PRIVATE(self)->ip_state_x[IS_IPv4];
}
-static void
-dad6_add_pending_address(NMDevice * self,
- NMPlatform * platform,
- int ifindex,
- const struct in6_addr *address,
- NMIP6Config ** dad6_config)
-{
- const NMPlatformIP6Address *pl_addr;
-
- pl_addr = nm_platform_ip6_address_get(platform, ifindex, address);
- if (pl_addr && NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_TENTATIVE)
- && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_DADFAILED)
- && !NM_FLAGS_HAS(pl_addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
- _LOGt(LOGD_DEVICE,
- "IPv6 DAD: pending address %s",
- nm_platform_ip6_address_to_string(pl_addr, NULL, 0));
-
- if (!*dad6_config)
- *dad6_config = nm_device_ip6_config_new(self);
-
- nm_ip6_config_add_address(*dad6_config, pl_addr);
- }
-}
-
-/*
- * Returns a NMIP6Config containing NM-configured addresses which
- * have the tentative flag, or NULL if none is present.
- */
-static NMIP6Config *
-dad6_get_pending_addresses(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP6Config * confs[] = {(NMIP6Config *) applied_config_get_current(&priv->ac_ip6_config),
- (NMIP6Config *) applied_config_get_current(&priv->dhcp6.ip6_config),
- priv->con_ip_config_6,
- (NMIP6Config *) applied_config_get_current(&priv->dev2_ip_config_6)};
- const NMPlatformIP6Address *addr;
- NMIP6Config * dad6_config = NULL;
- NMDedupMultiIter ipconf_iter;
- guint i;
- int ifindex;
- NMPlatform * platform;
-
- ifindex = nm_device_get_ip_ifindex(self);
- g_return_val_if_fail(ifindex > 0, NULL);
-
- platform = nm_device_get_platform(self);
-
- if (priv->ipv6ll_has) {
- dad6_add_pending_address(self, platform, ifindex, &priv->ipv6ll_addr, &dad6_config);
- }
-
- /* We are interested only in addresses that we have explicitly configured,
- * not in externally added ones.
- */
- for (i = 0; i < G_N_ELEMENTS(confs); i++) {
- if (!confs[i])
- continue;
-
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, confs[i], &addr) {
- dad6_add_pending_address(self, platform, ifindex, &addr->address, &dad6_config);
- }
- }
-
- return dad6_config;
-}
-
/*****************************************************************************/
static void
@@ -12181,21 +12150,6 @@ act_request_set(NMDevice *self, NMActRequest *act_request)
}
}
-static void
-dnsmasq_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (!priv->dnsmasq_manager)
- return;
-
- nm_clear_g_signal_handler(priv->dnsmasq_manager, &priv->dnsmasq_state_id);
-
- nm_dnsmasq_manager_stop(priv->dnsmasq_manager);
- g_object_unref(priv->dnsmasq_manager);
- priv->dnsmasq_manager = NULL;
-}
-
gboolean
nm_device_is_nm_owned(NMDevice *self)
{
@@ -12287,26 +12241,14 @@ _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type)
_set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_NONE);
- if (nm_clear_g_source(&priv->queued_ip_config_id_x[IS_IPv4])) {
- _LOGD(LOGD_DEVICE,
- "clearing queued IP%c config change",
- nm_utils_addr_family_to_char(addr_family));
- }
+ _dev_dhcpx_cleanup(self, addr_family, TRUE, FALSE);
if (IS_IPv4) {
- dhcp4_cleanup(self, cleanup_type, FALSE);
- arp_cleanup(self);
- dnsmasq_cleanup(self);
- ipv4ll_cleanup(self);
- g_slist_free_full(priv->acd.dad_list, (GDestroyNotify) nm_acd_manager_free);
- priv->acd.dad_list = NULL;
+ _dev_shared4_cleanup(self);
+ _dev_ll4_cleanup(self);
} else {
- g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
- priv->dad6_failed_addrs = NULL;
- g_clear_object(&priv->dad6_ip6_config);
- dhcp6_cleanup(self, cleanup_type, FALSE);
nm_clear_g_source(&priv->linklocal6_timeout_id);
- addrconf6_cleanup(self);
+ _dev_ac6_cleanup(self);
}
}
@@ -12396,37 +12338,6 @@ nm_device_reactivate_ip_config(NMDevice * self,
if (priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_NONE)
return;
- g_clear_object(&priv->con_ip_config_x[IS_IPv4]);
- g_clear_object(&priv->ext_ip_config_x[IS_IPv4]);
- if (IS_IPv4) {
- g_clear_object(&priv->dev_ip_config_4.current);
- } else {
- g_clear_object(&priv->ac_ip6_config.current);
- g_clear_object(&priv->dhcp6.ip6_config.current);
- }
- g_clear_object(&priv->dev2_ip_config_x[IS_IPv4].current);
-
- if (!IS_IPv4) {
- if (priv->ipv6ll_handle && !IN6_IS_ADDR_UNSPECIFIED(&priv->ipv6ll_addr))
- priv->ipv6ll_has = TRUE;
- }
-
- priv->con_ip_config_x[IS_IPv4] = nm_device_ip_config_new(self, addr_family);
-
- if (IS_IPv4) {
- nm_ip4_config_merge_setting(priv->con_ip_config_4,
- s_ip_new,
- _prop_get_connection_mdns(self),
- _prop_get_connection_llmnr(self),
- nm_device_get_route_table(self, AF_INET),
- nm_device_get_route_metric(self, AF_INET));
- } else {
- nm_ip6_config_merge_setting(priv->con_ip_config_6,
- s_ip_new,
- nm_device_get_route_table(self, AF_INET6),
- nm_device_get_route_metric(self, AF_INET6));
- }
-
method_old = (s_ip_old ? nm_setting_ip_config_get_method(s_ip_old) : NULL)
?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED
: NM_SETTING_IP6_CONFIG_METHOD_IGNORE);
@@ -12445,58 +12356,7 @@ nm_device_reactivate_ip_config(NMDevice * self,
return;
}
- if (s_ip_old && s_ip_new) {
- gint64 metric_old, metric_new;
-
- /* For dynamic IP methods (DHCP, IPv4LL, WWAN) the route metric is
- * set at activation/renewal time using the value from static
- * configuration. To support runtime change we need to update the
- * dynamic configuration in place and tell the DHCP client the new
- * value to use for future renewals.
- */
- metric_old = nm_setting_ip_config_get_route_metric(s_ip_old);
- metric_new = nm_setting_ip_config_get_route_metric(s_ip_new);
-
- if (metric_old != metric_new) {
- if (IS_IPv4) {
- if (priv->dev_ip_config_4.orig) {
- nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev_ip_config_4.orig,
- nm_device_get_route_metric(self, AF_INET));
- }
- if (priv->dev2_ip_config_4.orig) {
- nm_ip4_config_update_routes_metric((NMIP4Config *) priv->dev2_ip_config_4.orig,
- nm_device_get_route_metric(self, AF_INET));
- }
- if (priv->dhcp_data_4.client) {
- nm_dhcp_client_set_route_metric(priv->dhcp_data_4.client,
- nm_device_get_route_metric(self, AF_INET));
- }
- } else {
- if (priv->ac_ip6_config.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->ac_ip6_config.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dhcp6.ip6_config.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dhcp6.ip6_config.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dev2_ip_config_6.orig) {
- nm_ip6_config_update_routes_metric((NMIP6Config *) priv->dev2_ip_config_6.orig,
- nm_device_get_route_metric(self, AF_INET6));
- }
- if (priv->dhcp_data_6.client) {
- nm_dhcp_client_set_route_metric(priv->dhcp_data_6.client,
- nm_device_get_route_metric(self, AF_INET6));
- }
- }
- }
- }
-
- if (nm_device_get_ip_ifindex(self) > 0 && !ip_config_merge_and_apply(self, addr_family, TRUE)) {
- _LOGW(LOGD_IPX(IS_IPv4),
- "Failed to reapply IPv%c configuration",
- nm_utils_addr_family_to_char(addr_family));
- }
+ _dev_l3_cfg_commit(self);
}
static void
@@ -12520,7 +12380,7 @@ reactivate_proxy_config(NMDevice *self)
if (!priv->pacrunner_conf_id)
return;
- nm_device_set_proxy_config(self, priv->dhcp4.pac_url);
+ nm_device_set_proxy_config(self);
_pacrunner_manager_add(self);
}
@@ -12741,6 +12601,7 @@ check_and_reapply_connection(NMDevice * self,
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
/**************************************************************************
* Reapply changes
@@ -13000,96 +12861,6 @@ impl_device_get_applied_connection(NMDBusObject * obj,
/*****************************************************************************/
-typedef struct {
- gint64 timestamp_ms;
- bool dirty;
-} IP6RoutesTemporaryNotAvailableData;
-
-static gboolean
-_rt6_temporary_not_available_timeout(gpointer user_data)
-{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->rt6_temporary_not_available_id = 0;
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-_rt6_temporary_not_available_set(NMDevice *self, GPtrArray *temporary_not_available)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- IP6RoutesTemporaryNotAvailableData *data;
- GHashTableIter iter;
- gint64 now_ms, oldest_ms;
- const gint64 MAX_AGE_MS = 20000;
- guint i;
- gboolean success = TRUE;
-
- if (!temporary_not_available || !temporary_not_available->len) {
- /* nothing outstanding. Clear tracking the routes. */
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- return success;
- }
-
- if (priv->rt6_temporary_not_available) {
- g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data))
- data->dirty = TRUE;
- } else {
- priv->rt6_temporary_not_available =
- g_hash_table_new_full((GHashFunc) nmp_object_id_hash,
- (GEqualFunc) nmp_object_id_equal,
- (GDestroyNotify) nmp_object_unref,
- nm_g_slice_free_fcn(IP6RoutesTemporaryNotAvailableData));
- }
-
- now_ms = nm_utils_get_monotonic_timestamp_msec();
- oldest_ms = now_ms;
-
- for (i = 0; i < temporary_not_available->len; i++) {
- const NMPObject *o = temporary_not_available->pdata[i];
-
- data = g_hash_table_lookup(priv->rt6_temporary_not_available, o);
- if (data) {
- if (!data->dirty)
- continue;
- data->dirty = FALSE;
- nm_assert(data->timestamp_ms > 0 && data->timestamp_ms <= now_ms);
- if (now_ms > data->timestamp_ms + MAX_AGE_MS) {
- /* timeout. Could not add this address. */
- _LOGW(LOGD_DEVICE,
- "failure to add IPv6 route: %s",
- nmp_object_to_string(o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
- success = FALSE;
- } else
- oldest_ms = MIN(data->timestamp_ms, oldest_ms);
- continue;
- }
-
- data = g_slice_new0(IP6RoutesTemporaryNotAvailableData);
- data->timestamp_ms = now_ms;
- g_hash_table_insert(priv->rt6_temporary_not_available, (gpointer) nmp_object_ref(o), data);
- }
-
- g_hash_table_iter_init(&iter, priv->rt6_temporary_not_available);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &data)) {
- if (data->dirty)
- g_hash_table_iter_remove(&iter);
- }
-
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- priv->rt6_temporary_not_available_id =
- g_timeout_add(oldest_ms + MAX_AGE_MS - now_ms, _rt6_temporary_not_available_timeout, self);
-
- return success;
-}
-
-/*****************************************************************************/
-
static void
disconnect_cb(NMDevice * self,
GDBusMethodInvocation *context,
@@ -13481,11 +13252,12 @@ nm_device_get_proxy_config(NMDevice *self)
}
static void
-nm_device_set_proxy_config(NMDevice *self, const char *pac_url)
+nm_device_set_proxy_config(NMDevice *self)
{
NMDevicePrivate *priv;
NMConnection * connection;
NMSettingProxy * s_proxy = NULL;
+ const char * pac_url = NULL;
g_return_if_fail(NM_IS_DEVICE(self));
@@ -13494,6 +13266,14 @@ nm_device_set_proxy_config(NMDevice *self, const char *pac_url)
g_clear_object(&priv->proxy_config);
priv->proxy_config = nm_proxy_config_new();
+ if (priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d) {
+ NMDhcpLease *lease;
+
+ lease =
+ nm_l3_config_data_get_dhcp_lease(priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d, AF_INET);
+ pac_url = nm_dhcp_lease_lookup_option(lease, "wpad");
+ }
+
if (pac_url) {
nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
nm_proxy_config_set_pac_url(priv->proxy_config, pac_url);
@@ -13509,278 +13289,52 @@ nm_device_set_proxy_config(NMDevice *self, const char *pac_url)
nm_proxy_config_merge_setting(priv->proxy_config, s_proxy);
}
-/* IP Configuration stuff */
NMDhcpConfig *
nm_device_get_dhcp_config(NMDevice *self, int addr_family)
{
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
- nm_assert_addr_family(addr_family);
-
- return NM_DEVICE_GET_PRIVATE(self)->dhcp_data_x[IS_IPv4].config;
+ return NM_DEVICE_GET_PRIVATE(self)->dhcp_data_x[NM_IS_IPv4(addr_family)].config;
}
-NMIP4Config *
-nm_device_get_ip4_config(NMDevice *self)
+const NML3Cfg *
+nm_device_get_l3cfg(NMDevice *self)
{
g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
- return NM_DEVICE_GET_PRIVATE(self)->ip_config_4;
+ return NM_DEVICE_GET_PRIVATE(self)->l3cfg;
}
-static gboolean
-nm_device_set_ip_config(NMDevice * self,
- int addr_family,
- NMIPConfig *new_config,
- gboolean commit,
- GPtrArray * ip4_dev_route_blacklist)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMIPConfig * old_config;
- gboolean has_changes = FALSE;
- gboolean success = TRUE;
- NMSettingsConnection * settings_connection;
- NMIPRouteTableSyncMode route_table_sync_mode;
-
- nm_assert_addr_family(addr_family);
- nm_assert(!new_config || nm_ip_config_get_addr_family(new_config) == addr_family);
- nm_assert(!new_config
- || (new_config && ({
- int ip_ifindex = nm_device_get_ip_ifindex(self);
-
- (ip_ifindex > 0 && ip_ifindex == nm_ip_config_get_ifindex(new_config));
- })));
- nm_assert(IS_IPv4 || !ip4_dev_route_blacklist);
-
- if (commit && new_config)
- route_table_sync_mode = _get_route_table_sync_mode_stateful(self, addr_family);
- else
- route_table_sync_mode = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE;
-
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: update (commit=%d, new-config=" NM_HASH_OBFUSCATE_PTR_FMT
- ", route-table-sync-mode=%d)",
- nm_utils_addr_family_to_char(addr_family),
- commit,
- NM_HASH_OBFUSCATE_PTR(new_config),
- (int) route_table_sync_mode);
-
- /* Always commit to nm-platform to update lifetimes */
- if (commit && new_config) {
- _commit_mtu(self, IS_IPv4 ? NM_IP4_CONFIG(new_config) : priv->ip_config_4);
-
- if (IS_IPv4) {
- success = nm_ip4_config_commit(NM_IP4_CONFIG(new_config),
- nm_device_get_platform(self),
- route_table_sync_mode);
- nm_platform_ip4_dev_route_blacklist_set(nm_device_get_platform(self),
- nm_ip_config_get_ifindex(new_config),
- ip4_dev_route_blacklist);
- } else {
- gs_unref_ptrarray GPtrArray *temporary_not_available = NULL;
-
- success = nm_ip6_config_commit(NM_IP6_CONFIG(new_config),
- nm_device_get_platform(self),
- route_table_sync_mode,
- &temporary_not_available);
-
- if (!_rt6_temporary_not_available_set(self, temporary_not_available))
- success = FALSE;
- }
- }
-
- old_config = priv->ip_config_x[IS_IPv4];
-
- if (new_config && old_config) {
- /* has_changes is set only on relevant changes, because when the configuration changes,
- * this causes a re-read and reset. This should only happen for relevant changes */
- nm_ip_config_replace(old_config, new_config, &has_changes);
- if (has_changes) {
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: update IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config)));
- }
- } else if (new_config /*&& !old_config*/) {
- has_changes = TRUE;
- priv->ip_config_x[IS_IPv4] = g_object_ref(new_config);
- if (!nm_dbus_object_is_exported(NM_DBUS_OBJECT(new_config)))
- nm_dbus_object_export(NM_DBUS_OBJECT(new_config));
-
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: set IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(new_config)));
- } else if (old_config /*&& !new_config*/) {
- has_changes = TRUE;
- priv->ip_config_x[IS_IPv4] = NULL;
- _LOGD(LOGD_IPX(IS_IPv4),
- "ip%c-config: clear IP Config instance (%s)",
- nm_utils_addr_family_to_char(addr_family),
- nm_dbus_object_get_path(NM_DBUS_OBJECT(old_config)));
- if (IS_IPv4) {
- /* Device config is invalid if combined config is invalid */
- applied_config_clear(&priv->dev_ip_config_4);
- } else
- priv->needs_ip6_subnet = FALSE;
- }
-
- if (has_changes) {
- if (old_config != priv->ip_config_x[IS_IPv4])
- _notify(self, IS_IPv4 ? PROP_IP4_CONFIG : PROP_IP6_CONFIG);
-
- g_signal_emit(self,
- signals[IS_IPv4 ? IP4_CONFIG_CHANGED : IP6_CONFIG_CHANGED],
- 0,
- priv->ip_config_x[IS_IPv4],
- old_config);
-
- if (old_config != priv->ip_config_x[IS_IPv4])
- nm_dbus_object_clear_and_unexport(&old_config);
-
- if (nm_device_sys_iface_state_is_external(self)
- && (settings_connection = nm_device_get_settings_connection(self))
- && NM_FLAGS_HAS(nm_settings_connection_get_flags(settings_connection),
- NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)
- && nm_active_connection_get_activation_type(NM_ACTIVE_CONNECTION(priv->act_request.obj))
- == NM_ACTIVATION_TYPE_EXTERNAL) {
- gs_unref_object NMConnection *new_connection = NULL;
-
- new_connection = nm_simple_connection_new_clone(
- nm_settings_connection_get_connection(settings_connection));
-
- nm_connection_add_setting(
- new_connection,
- IS_IPv4 ? nm_ip4_config_create_setting(priv->ip_config_4)
- : nm_ip6_config_create_setting(priv->ip_config_6,
- _get_maybe_ipv6_disabled(self)));
-
- nm_settings_connection_update(settings_connection,
- new_connection,
- NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY,
- NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
- NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
- NM_SETTINGS_CONNECTION_UPDATE_REASON_UPDATE_NON_SECRET,
- "update-external",
- NULL);
- }
-
- nm_device_queue_recheck_assume(self);
-
- if (!IS_IPv4) {
- if (priv->ndisc)
- ndisc_set_router_config(priv->ndisc, self);
- }
- }
-
- nm_assert(!old_config || old_config == priv->ip_config_x[IS_IPv4]);
-
- return success;
-}
-
-static gboolean
-_replace_vpn_config_in_list(GSList **plist, GObject *old, GObject *new)
-{
- GSList *old_link;
-
- /* Below, assert that @new is not yet tracked, but still behave
- * correctly in any case. Don't complain for missing @old since
- * it could have been removed when the parent device became
- * unmanaged. */
-
- if (old && (old_link = g_slist_find(*plist, old))) {
- if (old != new) {
- if (new)
- old_link->data = g_object_ref(new);
- else
- *plist = g_slist_delete_link(*plist, old_link);
- g_object_unref(old);
- }
- return TRUE;
- }
-
- if (new) {
- if (!g_slist_find(*plist, new))
- *plist = g_slist_append(*plist, g_object_ref(new));
- else
- g_return_val_if_reached(TRUE);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-nm_device_replace_vpn4_config(NMDevice *self, NMIP4Config *old, NMIP4Config *config)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_assert(!old || NM_IS_IP4_CONFIG(old));
- nm_assert(!config || NM_IS_IP4_CONFIG(config));
- nm_assert(!old || nm_ip4_config_get_ifindex(old) == nm_device_get_ip_ifindex(self));
- nm_assert(!config || nm_ip4_config_get_ifindex(config) == nm_device_get_ip_ifindex(self));
-
- if (!_replace_vpn_config_in_list(&priv->vpn_configs_4, (GObject *) old, (GObject *) config))
- return;
-
- /* NULL to use existing configs */
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed to set VPN routes for device");
-}
-
-void
-nm_device_set_dev2_ip_config(NMDevice *self, int addr_family, NMIPConfig *config)
+const NML3ConfigData *
+nm_device_get_l3cd(NMDevice *self, gboolean get_commited)
{
NMDevicePrivate *priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- g_return_if_fail(NM_IS_DEVICE(self));
- g_return_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6));
- g_return_if_fail(!config || nm_ip_config_get_addr_family(config) == addr_family);
+ g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
priv = NM_DEVICE_GET_PRIVATE(self);
- applied_config_init(&priv->dev2_ip_config_x[IS_IPv4], config);
- if (!ip_config_merge_and_apply(self, addr_family, TRUE)) {
- _LOGW(LOGD_IP,
- "failed to set extra device IPv%c configuration",
- nm_utils_addr_family_to_char(addr_family));
- }
-}
-
-void
-nm_device_replace_vpn6_config(NMDevice *self, NMIP6Config *old, NMIP6Config *config)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_assert(!old || NM_IS_IP6_CONFIG(old));
- nm_assert(!config || NM_IS_IP6_CONFIG(config));
- nm_assert(!old || nm_ip6_config_get_ifindex(old) == nm_device_get_ip_ifindex(self));
- nm_assert(!config || nm_ip6_config_get_ifindex(config) == nm_device_get_ip_ifindex(self));
-
- if (!_replace_vpn_config_in_list(&priv->vpn_configs_6, (GObject *) old, (GObject *) config))
- return;
+ if (!priv->l3cfg)
+ return NULL;
- /* NULL to use existing configs */
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed to set VPN routes for device");
+ return nm_l3cfg_get_combined_l3cd(priv->l3cfg, get_commited);
}
-NMIP6Config *
-nm_device_get_ip6_config(NMDevice *self)
+void
+nm_device_set_dev2_ip_config(NMDevice *self, int addr_family, const NML3ConfigData *l3cd)
{
- g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
+ const gboolean IS_IPv4 = NM_IS_IPv4(addr_family);
- return NM_DEVICE_GET_PRIVATE(self)->ip_config_6;
+ _dev_l3_register_l3cds_set_one(self,
+ IS_IPv4 ? L3_CONFIG_DATA_TYPE_DEV_4 : L3_CONFIG_DATA_TYPE_DEV_6,
+ l3cd);
+ _dev_l3_cfg_commit(self);
}
/*****************************************************************************/
static gboolean
-dispatcher_cleanup(NMDevice *self)
+_dispatcher_cleanup(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13794,7 +13348,7 @@ dispatcher_cleanup(NMDevice *self)
}
static void
-dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data)
+_dispatcher_complete_proceed_state(NMDispatcherCallId *call_id, gpointer user_data)
{
NMDevice * self = NM_DEVICE(user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13814,7 +13368,7 @@ ip_check_pre_up(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- if (dispatcher_cleanup(self))
+ if (_dispatcher_cleanup(self))
nm_assert_not_reached();
priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES;
@@ -13822,11 +13376,11 @@ ip_check_pre_up(NMDevice *self)
if (!nm_dispatcher_call_device(NM_DISPATCHER_ACTION_PRE_UP,
self,
NULL,
- dispatcher_complete_proceed_state,
+ _dispatcher_complete_proceed_state,
self,
&priv->dispatcher.call_id)) {
/* Just proceed on errors */
- dispatcher_complete_proceed_state(0, self);
+ _dispatcher_complete_proceed_state(0, self);
}
}
@@ -14018,17 +13572,21 @@ nm_device_start_ip_check(NMDevice *self)
buf[0] = '\0';
if (timeout) {
- const NMPObject *gw;
+ const NMPObject * gw;
+ const NML3ConfigData *l3cd;
- if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- gw = nm_ip4_config_best_default_route_get(priv->ip_config_4);
+ l3cd = priv->l3cfg ? nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE) : NULL;
+ if (!l3cd) {
+ /* pass */
+ } else if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
+ gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET);
if (gw) {
_nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(gw)->gateway, buf);
ping_binary = nm_utils_find_helper("ping", "/usr/bin/ping", NULL);
log_domain = LOGD_IP4;
}
- } else if (priv->ip_config_6 && priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
- gw = nm_ip6_config_best_default_route_get(priv->ip_config_6);
+ } else if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
+ gw = nm_l3_config_data_get_best_default_route(l3cd, AF_INET6);
if (gw) {
_nm_utils_inet6_ntop(&NMP_OBJECT_CAST_IP6_ROUTE(gw)->gateway, buf);
ping_binary = nm_utils_find_helper("ping6", "/usr/bin/ping6", NULL);
@@ -14167,15 +13725,7 @@ nm_device_bring_up(NMDevice *self, gboolean block, gboolean *no_firmware)
/* Can only get HW address of some devices when they are up */
nm_device_update_hw_address(self);
- /* when the link comes up, we must restore IP configuration if necessary. */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE) {
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE))
- _LOGW(LOGD_IP4, "failed applying IP4 config after bringing link up");
- }
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_DONE) {
- if (!ip_config_merge_and_apply(self, AF_INET6, TRUE))
- _LOGW(LOGD_IP6, "failed applying IP6 config after bringing link up");
- }
+ _dev_l3_cfg_commit(self);
return TRUE;
}
@@ -14238,43 +13788,10 @@ nm_device_get_firmware_missing(NMDevice *self)
return NM_DEVICE_GET_PRIVATE(self)->firmware_missing;
}
-static void
-intersect_ext_config(NMDevice * self,
- AppliedConfig *config,
- gboolean intersect_addresses,
- gboolean intersect_routes)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIPConfig * ext;
- guint32 penalty;
- int family;
-
- if (!config->orig)
- return;
-
- family = nm_ip_config_get_addr_family(config->orig);
- penalty = default_route_metric_penalty_get(self, family);
- ext = family == AF_INET ? (NMIPConfig *) priv->ext_ip_config_4
- : (NMIPConfig *) priv->ext_ip_config_6;
-
- if (config->current) {
- nm_ip_config_intersect(config->current,
- ext,
- intersect_addresses,
- intersect_routes,
- penalty);
- } else {
- config->current = nm_ip_config_intersect_alloc(config->orig,
- ext,
- intersect_addresses,
- intersect_routes,
- penalty);
- }
-}
-
static gboolean
update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs)
{
+#if 0 //XXX
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
int ifindex;
GSList * iter;
@@ -14401,6 +13918,7 @@ update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs
nm_ip6_config_subtract(priv->ext_ip_config_6, iter->data, 0);
}
}
+#endif
return TRUE;
}
@@ -14408,6 +13926,7 @@ update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs
static void
update_ip_config(NMDevice *self, int addr_family)
{
+#if 0 //XXX
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
nm_assert_addr_family(addr_family);
@@ -14426,22 +13945,13 @@ update_ip_config(NMDevice *self, int addr_family)
ip_config_merge_and_apply(self, AF_INET6, FALSE);
}
}
-}
-
-void
-nm_device_capture_initial_config(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- if (!priv->update_ip_config_completed_v4)
- update_ip_config(self, AF_INET);
- if (!priv->update_ip_config_completed_v6)
- update_ip_config(self, AF_INET6);
+#endif
}
static gboolean
queued_ip_config_change(NMDevice *self, int addr_family)
{
+#if 0 //XXX
NMDevicePrivate *priv;
const int IS_IPv4 = NM_IS_IPv4(addr_family);
@@ -14542,6 +14052,7 @@ queued_ip_config_change(NMDevice *self, int addr_family)
set_unmanaged_external_down(self, TRUE);
+#endif
return G_SOURCE_REMOVE;
}
@@ -14565,6 +14076,7 @@ device_ipx_changed(NMPlatform * platform,
int change_type_i,
NMDevice * self)
{
+#if 0 //XXX
const NMPObjectType obj_type = obj_type_i;
const NMPlatformSignalChangeType change_type = change_type_i;
NMDevicePrivate * priv;
@@ -14611,6 +14123,7 @@ device_ipx_changed(NMPlatform * platform,
default:
g_return_if_reached();
}
+#endif
}
/*****************************************************************************/
@@ -14865,12 +14378,6 @@ _set_unmanaged_flags(NMDevice * self,
nm_device_set_unmanaged_flags(self, NM_UNMANAGED_USER_SETTINGS, !!unmanaged);
}
- /* trigger an initial update of IP configuration. */
- nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_4));
- nm_assert_se(!nm_clear_g_source(&priv->queued_ip_config_id_6));
- priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self);
- priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self);
-
if (!priv->pending_actions) {
do_notify_has_pending_actions = TRUE;
had_pending_actions = nm_device_has_pending_action(self);
@@ -15236,9 +14743,13 @@ nm_device_update_metered(NMDevice *self)
/* Try to guess a value using the metered flag in IP configuration */
if (value == NM_METERED_INVALID) {
- if (priv->ip_config_4 && priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE
- && nm_ip4_config_get_metered(priv->ip_config_4))
- value = NM_METERED_GUESS_YES;
+ if (priv->l3cfg) {
+ const NML3ConfigData *l3cd;
+
+ l3cd = nm_l3cfg_get_combined_l3cd(priv->l3cfg, TRUE);
+ if (l3cd && nm_l3_config_data_get_metered(l3cd))
+ value = NM_METERED_GUESS_YES;
+ }
}
/* Otherwise, look at connection type. For Bluetooth, we look at the type of
@@ -15806,7 +15317,7 @@ _cancel_activation(NMDevice *self)
priv->fw_state = FIREWALL_STATE_INITIALIZED;
}
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
ip_check_gw_ping_cleanup(self);
/* Break the activation chain */
@@ -15841,7 +15352,7 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type)
queued_state_clear(self);
- nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release);
+ _dev_shared4_cleanup(self);
for (i = 0; i < 2; i++)
nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free);
@@ -15860,6 +15371,7 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
priv->v4_route_table_initialized = FALSE;
priv->v6_route_table_initialized = FALSE;
+ priv->l3config_merge_flags_has = FALSE;
priv->v4_route_table_all_sync_before = FALSE;
priv->v6_route_table_all_sync_before = FALSE;
@@ -15869,39 +15381,19 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
priv->linklocal6_dad_counter = 0;
+ priv->ipv6ll_has = FALSE;
+ priv->ipv6ll_addr = nm_ip_addr_zero.addr6;
+
priv->mtu_force_set_done = FALSE;
/* Clean up IP configs; this does not actually deconfigure the
* interface; the caller must flush routes and addresses explicitly.
*/
- nm_device_set_ip_config(self, AF_INET, NULL, TRUE, NULL);
- nm_device_set_ip_config(self, AF_INET6, NULL, TRUE, NULL);
g_clear_object(&priv->proxy_config);
- g_clear_object(&priv->con_ip_config_4);
- applied_config_clear(&priv->dev_ip_config_4);
- applied_config_clear(&priv->dev2_ip_config_4);
- g_clear_object(&priv->ext_ip_config_4);
g_clear_object(&priv->ip_config_4);
- g_clear_object(&priv->con_ip_config_6);
- applied_config_clear(&priv->ac_ip6_config);
- g_clear_object(&priv->ext_ip_config_6);
- g_clear_object(&priv->ext_ip6_config_captured);
- applied_config_clear(&priv->dev2_ip_config_6);
g_clear_object(&priv->ip_config_6);
- g_clear_object(&priv->dad6_ip6_config);
- priv->ipv6ll_has = FALSE;
- memset(&priv->ipv6ll_addr, 0, sizeof(priv->ipv6ll_addr));
-
- nm_clear_pointer(&priv->rt6_temporary_not_available, g_hash_table_unref);
- nm_clear_g_source(&priv->rt6_temporary_not_available_id);
- g_slist_free_full(priv->vpn_configs_4, g_object_unref);
- priv->vpn_configs_4 = NULL;
- g_slist_free_full(priv->vpn_configs_6, g_object_unref);
- priv->vpn_configs_6 = NULL;
-
- /* We no longer accept the delegations. nm_device_set_ip_config(NULL)
- * above disables them. */
+ /* We no longer accept the delegations and don't expect the value to be set. */
nm_assert(priv->needs_ip6_subnet == FALSE);
if (priv->act_request.obj) {
@@ -16068,18 +15560,19 @@ deactivate_reset_hw_addr(NMDevice *self)
static char *
find_dhcp4_address(NMDevice *self)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const NMPlatformIP4Address *a;
- NMDedupMultiIter ipconf_iter;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const NMPObject *obj;
- if (!priv->ip_config_4)
+ if (!priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d)
return NULL;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, priv->ip_config_4, &a) {
- if (a->addr_source == NM_IP_CONFIG_SOURCE_DHCP)
- return nm_utils_inet4_ntop_dup(a->address);
- }
- return NULL;
+ obj = nm_l3_config_data_get_first_obj(priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d,
+ NMP_OBJECT_TYPE_IP4_ADDRESS,
+ NULL);
+ if (!obj)
+ return NULL;
+
+ return nm_utils_inet4_ntop_dup(NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address);
}
void
@@ -16091,7 +15584,6 @@ nm_device_spawn_iface_helper(NMDevice *self)
GError * error = NULL;
const char * method;
GPtrArray * argv;
- gs_free char * dhcp4_address = NULL;
char * logging_backend;
NMUtilsStableType stable_type;
const char * stable_id;
@@ -16136,10 +15628,9 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--log-domains"));
g_ptr_array_add(argv, g_strdup(nm_logging_domains_to_string()));
- dhcp4_address = find_dhcp4_address(self);
-
method = nm_device_get_effective_ip_config_method(self, AF_INET);
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+ char * dhcp4_address;
NMSettingIPConfig *s_ip4;
s_ip4 = nm_connection_get_setting_ip4_config(connection);
@@ -16148,8 +15639,12 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--priority4"));
g_ptr_array_add(argv, g_strdup_printf("%u", nm_device_get_route_metric(self, AF_INET)));
- g_ptr_array_add(argv, g_strdup("--dhcp4"));
- g_ptr_array_add(argv, g_strdup(dhcp4_address));
+ dhcp4_address = find_dhcp4_address(self);
+ if (dhcp4_address) {
+ g_ptr_array_add(argv, g_strdup("--dhcp4"));
+ g_ptr_array_add(argv, dhcp4_address);
+ }
+
if (nm_setting_ip_config_get_may_fail(s_ip4) == FALSE)
g_ptr_array_add(argv, g_strdup("--dhcp4-required"));
@@ -16199,7 +15694,7 @@ nm_device_spawn_iface_helper(NMDevice *self)
g_ptr_array_add(argv, g_strdup("--slaac-required"));
g_ptr_array_add(argv, g_strdup("--slaac-tempaddr"));
- g_ptr_array_add(argv, g_strdup_printf("%d", priv->ndisc_use_tempaddr));
+ g_ptr_array_add(argv, g_strdup_printf("%d", (int) priv->ac6_ip6_privacy));
if (nm_device_get_ip_iface_identifier(self, &iid, FALSE)) {
g_ptr_array_add(argv, g_strdup("--iid"));
@@ -16250,23 +15745,6 @@ nm_device_spawn_iface_helper(NMDevice *self)
/*****************************************************************************/
-static gboolean
-ip_config_valid(NMDeviceState state)
-{
- return (state == NM_DEVICE_STATE_UNMANAGED)
- || (state >= NM_DEVICE_STATE_IP_CHECK && state <= NM_DEVICE_STATE_DEACTIVATING);
-}
-
-static void
-notify_ip_properties(NMDevice *self)
-{
- _notify(self, PROP_IP_IFACE);
- _notify(self, PROP_IP4_CONFIG);
- _notify(self, PROP_DHCP4_CONFIG);
- _notify(self, PROP_IP6_CONFIG);
- _notify(self, PROP_DHCP6_CONFIG);
-}
-
static void
ip6_managed_setup(NMDevice *self)
{
@@ -16405,9 +15883,9 @@ deactivate_dispatcher_complete(NMDispatcherCallId *call_id, gpointer user_data)
static void
_set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting)
{
- NMDevicePrivate *priv;
- NMDeviceState old_state;
- gs_unref_object NMActRequest *req = NULL;
+ gs_unref_object NMActRequest *req = NULL;
+ NMDevicePrivate * priv;
+ NMDeviceState old_state;
gboolean no_firmware = FALSE;
NMSettingsConnection * sett_conn;
NMSettingSriov * s_sriov;
@@ -16417,8 +15895,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
priv = NM_DEVICE_GET_PRIVATE(self);
- /* Track re-entry */
- g_warn_if_fail(priv->in_state_changed == FALSE);
+ g_return_if_fail(priv->in_state_changed == 0);
old_state = priv->state;
@@ -16455,14 +15932,14 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
* by the device not having any pending action anymore
* we add one here that gets removed at the end of the function */
nm_device_add_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE);
- priv->in_state_changed = TRUE;
+ priv->in_state_changed++;
priv->state = state;
priv->state_reason = reason;
queued_state_clear(self);
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
nm_clear_g_cancellable(&priv->deactivating_cancellable);
@@ -16731,11 +16208,6 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
fw_change_zone(self);
} else
nm_device_start_ip_check(self);
-
- /* IP-related properties are only valid when the device has IP configuration;
- * now that it does, ensure their change notifications are emitted.
- */
- notify_ip_properties(self);
break;
}
case NM_DEVICE_STATE_SECONDARIES:
@@ -16758,18 +16230,13 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
}
}
- /* IP-related properties are only valid when the device has IP configuration.
- * If it no longer does, ensure their change notifications are emitted.
- */
- if (ip_config_valid(old_state) && !ip_config_valid(state))
- notify_ip_properties(self);
-
concheck_now = NM_IN_SET(state, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_DISCONNECTED)
|| old_state >= NM_DEVICE_STATE_ACTIVATED;
concheck_update_interval(self, AF_INET, concheck_now);
concheck_update_interval(self, AF_INET6, concheck_now);
- priv->in_state_changed = FALSE;
+ priv->in_state_changed--;
+
nm_device_remove_pending_action(self, NM_PENDING_ACTION_IN_STATE_CHANGE, TRUE);
if ((old_state > NM_DEVICE_STATE_UNMANAGED) != (state > NM_DEVICE_STATE_UNMANAGED))
@@ -17950,13 +17417,10 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
nm_utils_str_utf8safe_escape_cp(priv->iface, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_IP_IFACE:
- if (ip_config_valid(priv->state)) {
- g_value_take_string(
- value,
- nm_utils_str_utf8safe_escape_cp(nm_device_get_ip_iface(self),
- NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
- } else
- g_value_set_string(value, NULL);
+ g_value_take_string(
+ value,
+ nm_utils_str_utf8safe_escape_cp(nm_device_get_ip_iface(self),
+ NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL));
break;
case PROP_IFINDEX:
g_value_set_int(value, priv->ifindex);
@@ -17991,24 +17455,16 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
g_value_set_uint(value, priv->mtu);
break;
case PROP_IP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->state) ? priv->ip_config_4
- : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->ip_config_4);
break;
case PROP_DHCP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(
- value,
- ip_config_valid(priv->state) ? priv->dhcp_data_4.config : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->dhcp_data_4.config);
break;
case PROP_IP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->state) ? priv->ip_config_6
- : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->ip_config_6);
break;
case PROP_DHCP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(
- value,
- ip_config_valid(priv->state) ? priv->dhcp_data_6.config : NULL);
+ nm_dbus_utils_g_value_set_object_path(value, priv->dhcp_data_6.config);
break;
case PROP_STATE:
g_value_set_uint(value, priv->state);
@@ -18319,24 +17775,7 @@ constructed(GObject *object)
if (NM_DEVICE_GET_CLASS(self)->get_generic_capabilities)
priv->capabilities |= NM_DEVICE_GET_CLASS(self)->get_generic_capabilities(self);
- /* Watch for external IP config changes */
platform = nm_device_get_platform(self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
- g_signal_connect(platform,
- NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED,
- G_CALLBACK(device_ipx_changed),
- self);
g_signal_connect(platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK(link_changed_cb), self);
priv->manager = g_object_ref(NM_MANAGER_GET);
@@ -18388,15 +17827,12 @@ dispose(GObject *object)
_parent_set_ifindex(self, 0, FALSE);
platform = nm_device_get_platform(self);
- g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(device_ipx_changed), self);
g_signal_handlers_disconnect_by_func(platform, G_CALLBACK(link_changed_cb), self);
- arp_cleanup(self);
-
nm_clear_g_signal_handler(nm_config_get(), &priv->config_changed_id);
nm_clear_g_signal_handler(priv->manager, &priv->ifindex_changed_id);
- dispatcher_cleanup(self);
+ _dispatcher_cleanup(self);
nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
@@ -18474,7 +17910,6 @@ finalize(GObject *object)
g_free(priv->hw_addr_perm);
g_free(priv->hw_addr_initial);
g_slist_free(priv->pending_actions);
- g_slist_free_full(priv->dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
nm_clear_g_free(&priv->physical_port_id);
g_free(priv->udi);
g_free(priv->path);
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
index 72777d0aaf..a2e4493465 100644
--- a/src/core/devices/nm-device.h
+++ b/src/core/devices/nm-device.h
@@ -390,14 +390,15 @@ typedef struct _NMDeviceClass {
NMActStageReturn (*act_stage1_prepare)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
NMActStageReturn (*act_stage2_config)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
- NMActStageReturn (*act_stage3_ip_config_start)(NMDevice * self,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason);
+ NMActStageReturn (*act_stage3_ip_config_start)(NMDevice * self,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason);
NMActStageReturn (*act_stage4_ip_config_timeout)(NMDevice * self,
int addr_family,
NMDeviceStateReason *out_failure_reason);
+ //XXX: needs rework to not use NMIP4Config.
void (*ip4_config_pre_commit)(NMDevice *self, NMIP4Config *config);
/* Async deactivating (in the DEACTIVATING phase) */
@@ -507,13 +508,10 @@ const char *nm_device_get_initial_hw_address(NMDevice *dev);
NMProxyConfig *nm_device_get_proxy_config(NMDevice *dev);
NMDhcpConfig *nm_device_get_dhcp_config(NMDevice *dev, int addr_family);
-NMIP4Config * nm_device_get_ip4_config(NMDevice *dev);
-void nm_device_replace_vpn4_config(NMDevice *dev, NMIP4Config *old, NMIP4Config *config);
-NMIP6Config *nm_device_get_ip6_config(NMDevice *dev);
-void nm_device_replace_vpn6_config(NMDevice *dev, NMIP6Config *old, NMIP6Config *config);
+const NML3Cfg *nm_device_get_l3cfg(NMDevice *self);
-void nm_device_capture_initial_config(NMDevice *dev);
+const NML3ConfigData *nm_device_get_l3cd(NMDevice *self, gboolean get_commited);
int nm_device_parent_get_ifindex(NMDevice *dev);
NMDevice *nm_device_parent_get_device(NMDevice *dev);
diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c
index 37feb2f442..9107a1047c 100644
--- a/src/core/devices/ovs/nm-device-ovs-bridge.c
+++ b/src/core/devices/ovs/nm-device-ovs-bridge.c
@@ -67,10 +67,10 @@ get_generic_capabilities(NMDevice *device)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c
index 5d07c2117e..d6e33db730 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -180,10 +180,10 @@ set_platform_mtu(NMDevice *device, guint32 mtu)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device);
NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(device);
@@ -203,7 +203,7 @@ act_stage3_ip_config_start(NMDevice * device,
}
return NM_DEVICE_CLASS(nm_device_ovs_interface_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static gboolean
diff --git a/src/core/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c
index 2ecb95e881..0c089c466f 100644
--- a/src/core/devices/ovs/nm-device-ovs-port.c
+++ b/src/core/devices/ovs/nm-device-ovs-port.c
@@ -60,10 +60,10 @@ get_generic_capabilities(NMDevice *device)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
return NM_ACT_STAGE_RETURN_IP_FAIL;
}
diff --git a/src/core/devices/tests/meson.build b/src/core/devices/tests/meson.build
index 1bc883706e..871c320629 100644
--- a/src/core/devices/tests/meson.build
+++ b/src/core/devices/tests/meson.build
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
test_units = [
- 'test-acd',
'test-lldp',
]
diff --git a/src/core/devices/tests/test-acd.c b/src/core/devices/tests/test-acd.c
deleted file mode 100644
index b4b6516549..0000000000
--- a/src/core/devices/tests/test-acd.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "n-acd/src/n-acd.h"
-
-#include <linux/if_ether.h>
-
-#include "devices/nm-acd-manager.h"
-#include "platform/tests/test-common.h"
-
-#define IFACE_VETH0 "nm-test-veth0"
-#define IFACE_VETH1 "nm-test-veth1"
-
-#define ADDR1 0x01010101
-#define ADDR2 0x02020202
-#define ADDR3 0x03030303
-#define ADDR4 0x04040404
-
-/*****************************************************************************/
-
-static gboolean
-_skip_acd_test_check(void)
-{
- NAcd * acd;
- NAcdConfig * config;
- const guint8 hwaddr[ETH_ALEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
- int r;
- static int skip = -1;
-
- if (skip == -1) {
- r = n_acd_config_new(&config);
- g_assert(r == 0);
-
- n_acd_config_set_ifindex(config, 1);
- n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET);
- n_acd_config_set_mac(config, hwaddr, sizeof(hwaddr));
-
- r = n_acd_new(&acd, config);
- n_acd_config_free(config);
- if (r == 0)
- n_acd_unref(acd);
-
- skip = (r != 0);
- }
- return skip;
-}
-
-#define _skip_acd_test() \
- ({ \
- gboolean _skip = _skip_acd_test_check(); \
- \
- if (_skip) \
- g_test_skip("Cannot create NAcd. Running under valgind?"); \
- _skip; \
- })
-
-/*****************************************************************************/
-
-typedef struct {
- int ifindex0;
- int ifindex1;
- const guint8 *hwaddr0;
- const guint8 *hwaddr1;
- size_t hwaddr0_len;
- size_t hwaddr1_len;
-} test_fixture;
-
-static void
-fixture_setup(test_fixture *fixture, gconstpointer user_data)
-{
- /* create veth pair. */
- fixture->ifindex0 =
- nmtstp_link_veth_add(NM_PLATFORM_GET, -1, IFACE_VETH0, IFACE_VETH1)->ifindex;
- fixture->ifindex1 =
- nmtstp_link_get_typed(NM_PLATFORM_GET, -1, IFACE_VETH1, NM_LINK_TYPE_VETH)->ifindex;
-
- g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex0, IFF_UP, TRUE) >= 0);
- g_assert(nm_platform_link_change_flags(NM_PLATFORM_GET, fixture->ifindex1, IFF_UP, TRUE) >= 0);
-
- fixture->hwaddr0 =
- nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex0, &fixture->hwaddr0_len);
- fixture->hwaddr1 =
- nm_platform_link_get_address(NM_PLATFORM_GET, fixture->ifindex1, &fixture->hwaddr1_len);
-}
-
-typedef struct {
- in_addr_t addresses[8];
- in_addr_t peer_addresses[8];
- gboolean expected_result[8];
-} TestInfo;
-
-static void
-acd_manager_probe_terminated(NMAcdManager *acd_manager, gpointer user_data)
-{
- g_main_loop_quit(user_data);
-}
-
-static void
-test_acd_common(test_fixture *fixture, TestInfo *info)
-{
- nm_auto_free_acdmgr NMAcdManager *manager = NULL;
- nm_auto_unref_gmainloop GMainLoop *loop = NULL;
- int i;
- const guint WAIT_TIME_OPTIMISTIC = 50;
- guint wait_time;
- static const NMAcdCallbacks callbacks = {
- .probe_terminated_callback = acd_manager_probe_terminated,
- .user_data_destroy = (GDestroyNotify) g_main_loop_unref,
- };
- int r;
-
- if (_skip_acd_test())
- return;
-
- /* first, try with a short waittime. We hope that this is long enough
- * to successfully complete the test. Only if that's not the case, we
- * assume the computer is currently busy (high load) and we retry with
- * a longer timeout. */
- wait_time = WAIT_TIME_OPTIMISTIC;
-again:
-
- nm_clear_pointer(&loop, g_main_loop_unref);
- loop = g_main_loop_new(NULL, FALSE);
-
- nm_clear_pointer(&manager, nm_acd_manager_free);
- manager = nm_acd_manager_new(fixture->ifindex0,
- fixture->hwaddr0,
- fixture->hwaddr0_len,
- &callbacks,
- g_main_loop_ref(loop));
- g_assert(manager != NULL);
-
- for (i = 0; info->addresses[i]; i++)
- g_assert(nm_acd_manager_add_address(manager, info->addresses[i]));
-
- for (i = 0; info->peer_addresses[i]; i++) {
- nmtstp_ip4_address_add(NULL,
- FALSE,
- fixture->ifindex1,
- info->peer_addresses[i],
- 24,
- 0,
- 3600,
- 1800,
- 0,
- NULL);
- }
-
- r = nm_acd_manager_start_probe(manager, wait_time);
- g_assert_cmpint(r, ==, 0);
-
- g_assert(nmtst_main_loop_run(loop, 2000));
-
- for (i = 0; info->addresses[i]; i++) {
- gboolean val;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- val = nm_acd_manager_check_address(manager, info->addresses[i]);
- if (val == info->expected_result[i])
- continue;
-
- if (wait_time == WAIT_TIME_OPTIMISTIC) {
- /* probably we just had a glitch and the system took longer than
- * expected. Re-verify with a large timeout this time. */
- wait_time = 1000;
- goto again;
- }
-
- g_error("expected check for address #%d (%s) to %s, but it didn't",
- i,
- _nm_utils_inet4_ntop(info->addresses[i], sbuf),
- info->expected_result[i] ? "detect no duplicated" : "detect a duplicate");
- }
-}
-
-static void
-test_acd_probe_1(test_fixture *fixture, gconstpointer user_data)
-{
- TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3},
- .peer_addresses = {ADDR4},
- .expected_result = {TRUE, TRUE, TRUE}};
-
- test_acd_common(fixture, &info);
-}
-
-static void
-test_acd_probe_2(test_fixture *fixture, gconstpointer user_data)
-{
- TestInfo info = {.addresses = {ADDR1, ADDR2, ADDR3, ADDR4},
- .peer_addresses = {ADDR3, ADDR2},
- .expected_result = {TRUE, FALSE, FALSE, TRUE}};
-
- test_acd_common(fixture, &info);
-}
-
-static void
-test_acd_announce(test_fixture *fixture, gconstpointer user_data)
-{
- nm_auto_free_acdmgr NMAcdManager *manager = NULL;
- nm_auto_unref_gmainloop GMainLoop *loop = NULL;
- int r;
-
- if (_skip_acd_test())
- return;
-
- manager =
- nm_acd_manager_new(fixture->ifindex0, fixture->hwaddr0, fixture->hwaddr0_len, NULL, NULL);
- g_assert(manager != NULL);
-
- g_assert(nm_acd_manager_add_address(manager, ADDR1));
- g_assert(nm_acd_manager_add_address(manager, ADDR2));
-
- loop = g_main_loop_new(NULL, FALSE);
- r = nm_acd_manager_announce_addresses(manager);
- g_assert_cmpint(r, ==, 0);
- g_assert(!nmtst_main_loop_run(loop, 200));
-}
-
-static void
-fixture_teardown(test_fixture *fixture, gconstpointer user_data)
-{
- nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex0);
- nm_platform_link_delete(NM_PLATFORM_GET, fixture->ifindex1);
-}
-
-NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup;
-
-void
-_nmtstp_init_tests(int *argc, char ***argv)
-{
- nmtst_init_with_logging(argc, argv, NULL, "ALL");
-}
-
-void
-_nmtstp_setup_tests(void)
-{
- g_test_add("/acd/probe/1",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_probe_1,
- fixture_teardown);
- g_test_add("/acd/probe/2",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_probe_2,
- fixture_teardown);
- g_test_add("/acd/announce",
- test_fixture,
- NULL,
- fixture_setup,
- test_acd_announce,
- fixture_teardown);
-}
diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c
index 7ff0434ca9..1c7531da4d 100644
--- a/src/core/devices/wifi/nm-device-wifi-p2p.c
+++ b/src/core/devices/wifi/nm-device-wifi-p2p.c
@@ -555,10 +555,10 @@ remove_all_peers(NMDeviceWifiP2P *self)
/*****************************************************************************/
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
gboolean indicate_addressing_running;
NMConnection *connection;
@@ -582,7 +582,7 @@ act_stage3_ip_config_start(NMDevice * device,
TRUE);
return NM_DEVICE_CLASS(nm_device_wifi_p2p_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static void
diff --git a/src/core/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c
index 0d210f0ab4..5a8de56669 100644
--- a/src/core/devices/wifi/nm-device-wifi.c
+++ b/src/core/devices/wifi/nm-device-wifi.c
@@ -3271,10 +3271,10 @@ out_fail:
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
gboolean indicate_addressing_running;
NMConnection *connection;
@@ -3297,7 +3297,7 @@ act_stage3_ip_config_start(NMDevice * device,
TRUE);
return NM_DEVICE_CLASS(nm_device_wifi_parent_class)
- ->act_stage3_ip_config_start(device, addr_family, out_config, out_failure_reason);
+ ->act_stage3_ip_config_start(device, addr_family, out_l3cd, out_failure_reason);
}
static guint32
diff --git a/src/core/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c
index 405ced64a1..0b44b752e0 100644
--- a/src/core/devices/wwan/nm-device-modem.c
+++ b/src/core/devices/wwan/nm-device-modem.c
@@ -8,7 +8,7 @@
#include "nm-device-modem.h"
#include "nm-modem.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#include "devices/nm-device-private.h"
#include "nm-rfkill-manager.h"
#include "settings/nm-settings-connection.h"
@@ -33,6 +33,7 @@ typedef struct {
NMModem * modem;
NMDeviceModemCapabilities caps;
NMDeviceModemCapabilities current_caps;
+ NMUtilsIPv6IfaceId iid;
char * device_id;
char * operator_code;
char * apn;
@@ -188,35 +189,36 @@ modem_auth_result(NMModem *modem, GError *error, gpointer user_data)
}
static void
-modem_ip4_config_result(NMModem *modem, NMIP4Config *config, GError *error, gpointer user_data)
-{
- NMDeviceModem *self = NM_DEVICE_MODEM(user_data);
- NMDevice * device = NM_DEVICE(self);
+modem_new_config(NMModem * modem,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error,
+ gpointer user_data)
+{
+ NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
+ NMDeviceModemPrivate * priv = NM_DEVICE_MODEM_GET_PRIVATE(self);
+ NMDevice * device = NM_DEVICE(self);
+ NMActStageReturn ret;
+ NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_ignored = NULL;
- g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE);
+ if (addr_family == AF_INET) {
+ g_return_if_fail(nm_device_activate_ip4_state_in_conf(device) == TRUE);
- if (error) {
- _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message);
- nm_device_ip_method_failed(device, AF_INET, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
- } else {
- nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG_CAST(config));
- nm_device_activate_schedule_ip_config_result(device, AF_INET, NULL);
- }
-}
+ if (error) {
+ _LOGW(LOGD_MB | LOGD_IP4, "retrieving IPv4 configuration failed: %s", error->message);
+ nm_device_ip_method_failed(device,
+ AF_INET,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE);
+ return;
+ }
-static void
-modem_ip6_config_result(NMModem * modem,
- NMIP6Config *config,
- gboolean do_slaac,
- GError * error,
- gpointer user_data)
-{
- NMDeviceModem * self = NM_DEVICE_MODEM(user_data);
- NMDevice * device = NM_DEVICE(self);
- NMActStageReturn ret;
- NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE;
- gs_unref_object NMIP6Config *ignored = NULL;
- gboolean got_config = !!config;
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
+ return;
+ }
g_return_if_fail(nm_device_activate_ip6_state_in_conf(device) == TRUE);
@@ -226,15 +228,19 @@ modem_ip6_config_result(NMModem * modem,
return;
}
+ if (iid)
+ priv->iid = *iid;
+ else
+ priv->iid.id = 0;
+
/* Re-enable IPv6 on the interface */
nm_device_sysctl_ip_conf_set(device, AF_INET6, "disable_ipv6", "0");
- if (config)
- nm_device_set_dev2_ip_config(device, AF_INET6, NM_IP_CONFIG_CAST(config));
+ nm_device_set_dev2_ip_config(device, AF_INET6, l3cd);
if (do_slaac == FALSE) {
- if (got_config)
- nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL);
+ if (l3cd)
+ nm_device_activate_schedule_ip_config_result(device, AF_INET6);
else {
_LOGW(LOGD_MB | LOGD_IP6,
"retrieving IPv6 configuration failed: SLAAC not requested and no addresses");
@@ -246,11 +252,10 @@ modem_ip6_config_result(NMModem * modem,
}
/* Start SLAAC now that we have a link-local address from the modem */
- ret =
- NM_DEVICE_CLASS(nm_device_modem_parent_class)
- ->act_stage3_ip_config_start(device, AF_INET6, (gpointer *) &ignored, &failure_reason);
+ ret = NM_DEVICE_CLASS(nm_device_modem_parent_class)
+ ->act_stage3_ip_config_start(device, AF_INET6, &l3cd_ignored, &failure_reason);
- nm_assert(ignored == NULL);
+ nm_assert(!l3cd_ignored);
switch (ret) {
case NM_ACT_STAGE_RETURN_FAILURE:
@@ -258,7 +263,7 @@ modem_ip6_config_result(NMModem * modem,
break;
case NM_ACT_STAGE_RETURN_IP_FAIL:
/* all done */
- nm_device_activate_schedule_ip_config_result(device, AF_INET6, NULL);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET6);
break;
case NM_ACT_STAGE_RETURN_POSTPONE:
/* let SLAAC run */
@@ -602,10 +607,10 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
static NMActStageReturn
-act_stage3_ip_config_start(NMDevice * device,
- int addr_family,
- gpointer * out_config,
- NMDeviceStateReason *out_failure_reason)
+act_stage3_ip_config_start(NMDevice * device,
+ int addr_family,
+ const NML3ConfigData **out_l3cd,
+ NMDeviceStateReason * out_failure_reason)
{
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(device);
@@ -632,14 +637,15 @@ get_ip_iface_identifier(NMDevice *device, NMUtilsIPv6IfaceId *out_iid)
{
NMDeviceModem * self = NM_DEVICE_MODEM(device);
NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE(self);
- gboolean success;
g_return_val_if_fail(priv->modem, FALSE);
- success = nm_modem_get_iid(priv->modem, out_iid);
- if (!success)
- success =
- NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid);
- return success;
+
+ if (priv->iid.id != 0) {
+ *out_iid = priv->iid;
+ return TRUE;
+ }
+
+ return NM_DEVICE_CLASS(nm_device_modem_parent_class)->get_ip_iface_identifier(device, out_iid);
}
/*****************************************************************************/
@@ -705,8 +711,7 @@ set_modem(NMDeviceModem *self, NMModem *modem)
g_signal_connect(modem, NM_MODEM_PPP_FAILED, G_CALLBACK(ppp_failed), self);
g_signal_connect(modem, NM_MODEM_PREPARE_RESULT, G_CALLBACK(modem_prepare_result), self);
- g_signal_connect(modem, NM_MODEM_IP4_CONFIG_RESULT, G_CALLBACK(modem_ip4_config_result), self);
- g_signal_connect(modem, NM_MODEM_IP6_CONFIG_RESULT, G_CALLBACK(modem_ip6_config_result), self);
+ g_signal_connect(modem, NM_MODEM_NEW_CONFIG, G_CALLBACK(modem_new_config), self);
g_signal_connect(modem, NM_MODEM_AUTH_REQUESTED, G_CALLBACK(modem_auth_requested), self);
g_signal_connect(modem, NM_MODEM_AUTH_RESULT, G_CALLBACK(modem_auth_result), self);
g_signal_connect(modem, NM_MODEM_STATE_CHANGED, G_CALLBACK(modem_state_cb), self);
diff --git a/src/core/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c
index 0872a8a1f9..8535909625 100644
--- a/src/core/devices/wwan/nm-modem-broadband.c
+++ b/src/core/devices/wwan/nm-modem-broadband.c
@@ -15,8 +15,7 @@
#include "NetworkManagerUtils.h"
#include "devices/nm-device-private.h"
#include "libnm-platform/nm-platform.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#define NM_MODEM_BROADBAND_MODEM "modem"
@@ -964,21 +963,23 @@ set_mm_enabled(NMModem *_self, gboolean enabled)
/* IPv4 method static */
static gboolean
-static_stage3_ip4_done(NMModemBroadband *self)
+static_stage3_ip4_done(gpointer user_data)
{
- GError * error = NULL;
- gs_unref_object NMIP4Config *config = NULL;
- const char * data_port;
- const char * address_string;
- const char * gw_string;
- guint32 address_network;
- guint32 gw = 0;
- NMPlatformIP4Address address;
- const char ** dns;
- guint i;
- guint32 ip4_route_table, ip4_route_metric;
- NMPlatformIP4Route * r;
- guint32 mtu_n;
+ NMModemBroadband * self = user_data;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ gs_free_error GError *error = NULL;
+ const char * data_port;
+ const char * address_string;
+ const char * gw_string;
+ guint32 address_network;
+ guint32 gw = 0;
+ NMPlatformIP4Address address;
+ const char ** dns;
+ int ifindex;
+ guint i;
+ NMPlatformIP4Route route;
+ guint32 mtu_n;
g_return_val_if_fail(self->_priv.ipv4_config, FALSE);
g_return_val_if_fail(self->_priv.bearer, FALSE);
@@ -991,58 +992,72 @@ static_stage3_ip4_done(NMModemBroadband *self)
address_string = mm_bearer_ip_config_get_address(self->_priv.ipv4_config);
if (!address_string
|| !nm_utils_parse_inaddr_bin(AF_INET, address_string, NULL, &address_network)) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s",
- nm_modem_get_uid(NM_MODEM(self)),
- NM_PRINT_FMT_QUOTE_STRING(address_string));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IP4 configuration failed: invalid address given %s%s%s",
+ nm_modem_get_uid(NM_MODEM(self)),
+ NM_PRINT_FMT_QUOTE_STRING(address_string));
goto out;
}
/* Missing gateway not a hard failure */
gw_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv4_config);
if (gw_string && !nm_utils_parse_inaddr_bin(AF_INET, gw_string, NULL, &gw)) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"",
- nm_modem_get_uid(NM_MODEM(self)),
- gw_string);
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IP4 configuration failed: invalid gateway address \"%s\"",
+ nm_modem_get_uid(NM_MODEM(self)),
+ gw_string);
goto out;
}
data_port = mm_bearer_get_interface(self->_priv.bearer);
g_return_val_if_fail(data_port, FALSE);
- config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
- nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
-
- memset(&address, 0, sizeof(address));
- address.address = address_network;
- address.peer_address = address_network;
- address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config);
- address.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
+
+ ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port);
+ if (ifindex <= 0) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) data port %s not found",
+ nm_modem_get_uid(NM_MODEM(self)),
+ data_port);
+ goto out;
+ }
+
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex);
+
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_WWAN);
+
+ address = (NMPlatformIP4Address){
+ .address = address_network,
+ .peer_address = address_network,
+ .plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv4_config),
+ .addr_source = NM_IP_CONFIG_SOURCE_WWAN,
+ };
if (address.plen <= 32)
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
- _LOGI(" address %s/%d", address_string, address.plen);
+ _LOGI(" address %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf)));
- nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL);
- r = &(NMPlatformIP4Route){
+ route = (NMPlatformIP4Route){
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = gw,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(config, r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
_LOGI(" gateway %s", gw_string);
- /* DNS servers */
dns = mm_bearer_ip_config_get_dns(self->_priv.ipv4_config);
for (i = 0; dns && dns[i]; i++) {
if (nm_utils_parse_inaddr_bin(AF_INET, dns[i], NULL, &address_network)
&& address_network > 0) {
- nm_ip4_config_add_nameserver(config, address_network);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &address_network);
_LOGI(" DNS %s", dns[i]);
}
}
@@ -1050,15 +1065,17 @@ static_stage3_ip4_done(NMModemBroadband *self)
#if MM_CHECK_VERSION(1, 4, 0)
mtu_n = mm_bearer_ip_config_get_mtu(self->_priv.ipv4_config);
if (mtu_n) {
- nm_ip4_config_set_mtu(config, mtu_n, NM_IP_CONFIG_SOURCE_WWAN);
+ nm_l3_config_data_set_mtu(l3cd, mtu_n);
_LOGI(" MTU %u", mtu_n);
}
#endif
out:
- g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, config, error);
- g_clear_error(&error);
- return FALSE;
+ if (error)
+ nm_clear_l3cd(&l3cd);
+
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET, l3cd, FALSE, NULL, error);
+ return G_SOURCE_REMOVE;
}
static NMActStageReturn
@@ -1072,8 +1089,7 @@ static_stage3_ip4_config_start(NMModem * modem,
/* We schedule it in an idle just to follow the same logic as in the
* generic modem implementation. */
nm_clear_g_source(&priv->idle_id_ip4);
- priv->idle_id_ip4 = g_idle_add((GSourceFunc) static_stage3_ip4_done, self);
-
+ priv->idle_id_ip4 = g_idle_add(static_stage3_ip4_done, self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -1081,21 +1097,26 @@ static_stage3_ip4_config_start(NMModem * modem,
/* IPv6 method static */
static gboolean
-stage3_ip6_done(NMModemBroadband *self)
+stage3_ip6_done(gpointer user_data)
{
- GError * error = NULL;
- NMIP6Config * config = NULL;
- const char * data_port;
- const char * address_string;
- NMPlatformIP6Address address;
- NMModemIPMethod ip_method;
- const char ** dns;
- guint i;
-
- g_return_val_if_fail(self->_priv.ipv6_config, FALSE);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMModemBroadband * self = user_data;
+ gs_free_error GError * error = NULL;
+ const char * data_port;
+ const char * address_string;
+ NMPlatformIP6Address address;
+ NMModemIPMethod ip_method;
+ const char ** dns;
+ guint i;
+ gboolean do_slaac = TRUE;
+ int ifindex;
+ NMUtilsIPv6IfaceId iid_data;
+ const NMUtilsIPv6IfaceId *iid = NULL;
+
+ g_return_val_if_fail(self->_priv.ipv6_config, G_SOURCE_REMOVE);
self->_priv.idle_id_ip6 = 0;
- memset(&address, 0, sizeof(address));
ip_method = get_bearer_ip_method(self->_priv.ipv6_config);
@@ -1103,93 +1124,112 @@ stage3_ip6_done(NMModemBroadband *self)
if (!address_string) {
/* DHCP/SLAAC is allowed to skip addresses; other methods require it */
if (ip_method != NM_MODEM_IP_METHOD_AUTO) {
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: no address given",
- nm_modem_get_uid(NM_MODEM(self)));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: no address given",
+ nm_modem_get_uid(NM_MODEM(self)));
}
goto out;
}
- /* Fail if invalid IP address retrieved */
- if (!inet_pton(AF_INET6, address_string, (void *) &(address.address))) {
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
- nm_modem_get_uid(NM_MODEM(self)),
- address_string);
+ address = (NMPlatformIP6Address){};
+
+ if (!inet_pton(AF_INET6, address_string, &address.address)) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: invalid address given '%s'",
+ nm_modem_get_uid(NM_MODEM(self)),
+ address_string);
goto out;
}
- _LOGI("IPv6 base configuration:");
-
data_port = mm_bearer_get_interface(self->_priv.bearer);
- g_return_val_if_fail(data_port, FALSE);
+ g_return_val_if_fail(data_port, G_SOURCE_REMOVE);
+
+ ifindex = nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port);
+ if (ifindex <= 0) {
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) data port %s not found",
+ nm_modem_get_uid(NM_MODEM(self)),
+ data_port);
+ goto out;
+ }
+
+ _LOGI("IPv6 base configuration:");
- config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET),
- nm_platform_link_get_ifindex(NM_PLATFORM_GET, data_port));
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex);
address.plen = mm_bearer_ip_config_get_prefix(self->_priv.ipv6_config);
- if (address.plen <= 128)
- nm_ip6_config_add_address(config, &address);
+ if (address.plen <= 128) {
+ if (IN6_IS_ADDR_LINKLOCAL(&address.address)) {
+ iid_data.id = ((guint64 *) (&address.address.s6_addr))[1];
+ iid = &iid_data;
+ } else
+ do_slaac = FALSE;
+ nm_l3_config_data_add_address_6(l3cd, &address);
+ }
- _LOGI(" address %s/%d", address_string, address.plen);
+ _LOGI(" address %s (slaac %s)",
+ nm_platform_ip6_address_to_string(&address, sbuf, sizeof(sbuf)),
+ do_slaac ? "enabled" : "disabled");
address_string = mm_bearer_ip_config_get_gateway(self->_priv.ipv6_config);
if (address_string) {
- guint32 ip6_route_table, ip6_route_metric;
-
if (inet_pton(AF_INET6, address_string, &address.address) != 1) {
- error =
- g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
- nm_modem_get_uid(NM_MODEM(self)),
- address_string);
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: invalid gateway given '%s'",
+ nm_modem_get_uid(NM_MODEM(self)),
+ address_string);
goto out;
}
- nm_modem_get_route_parameters(NM_MODEM(self),
- NULL,
- NULL,
- &ip6_route_table,
- &ip6_route_metric);
{
const NMPlatformIP6Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = address.address,
- .table_coerced = nm_platform_route_table_coerce(ip6_route_table),
- .metric = ip6_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
_LOGI(" gateway %s", address_string);
- nm_ip6_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_6(l3cd, &r);
}
} else if (ip_method == NM_MODEM_IP_METHOD_STATIC) {
/* Gateway required for the 'static' method */
- error = g_error_new(NM_DEVICE_ERROR,
- NM_DEVICE_ERROR_INVALID_CONNECTION,
- "(%s) retrieving IPv6 configuration failed: missing gateway",
- nm_modem_get_uid(NM_MODEM(self)));
+ g_set_error(&error,
+ NM_DEVICE_ERROR,
+ NM_DEVICE_ERROR_INVALID_CONNECTION,
+ "(%s) retrieving IPv6 configuration failed: missing gateway",
+ nm_modem_get_uid(NM_MODEM(self)));
goto out;
}
- /* DNS servers */
dns = mm_bearer_ip_config_get_dns(self->_priv.ipv6_config);
for (i = 0; dns && dns[i]; i++) {
struct in6_addr addr;
if (inet_pton(AF_INET6, dns[i], &addr)) {
- nm_ip6_config_add_nameserver(config, &addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &addr);
_LOGI(" DNS %s", dns[i]);
}
}
out:
- nm_modem_emit_ip6_config_result(NM_MODEM(self), config, error);
- g_clear_object(&config);
- g_clear_error(&error);
- return FALSE;
+ if (error) {
+ nm_clear_l3cd(&l3cd);
+ do_slaac = FALSE;
+ iid = NULL;
+ }
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET6, l3cd, do_slaac, iid, error);
+ return G_SOURCE_REMOVE;
}
static NMActStageReturn
@@ -1201,7 +1241,7 @@ stage3_ip6_config_request(NMModem *modem, NMDeviceStateReason *out_failure_reaso
/* We schedule it in an idle just to follow the same logic as in the
* generic modem implementation. */
nm_clear_g_source(&priv->idle_id_ip6);
- priv->idle_id_ip6 = g_idle_add((GSourceFunc) stage3_ip6_done, self);
+ priv->idle_id_ip6 = g_idle_add(stage3_ip6_done, self);
return NM_ACT_STAGE_RETURN_POSTPONE;
}
diff --git a/src/core/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c
index 78ad7b6820..d31325d1f1 100644
--- a/src/core/devices/wwan/nm-modem-ofono.c
+++ b/src/core/devices/wwan/nm-modem-ofono.c
@@ -11,7 +11,7 @@
#include "devices/nm-device-private.h"
#include "nm-modem.h"
#include "libnm-platform/nm-platform.h"
-#include "nm-ip4-config.h"
+#include "nm-l3-config-data.h"
#define VARIANT_IS_OF_TYPE_BOOLEAN(v) \
((v) != NULL && (g_variant_is_of_type((v), G_VARIANT_TYPE_BOOLEAN)))
@@ -47,7 +47,7 @@ typedef struct {
gboolean modem_online;
gboolean gprs_attached;
- NMIP4Config *ip4_config;
+ NML3ConfigData *l3cd_4;
} NMModemOfonoPrivate;
struct _NMModemOfono {
@@ -240,7 +240,7 @@ deactivate_cleanup(NMModem *modem, NMDevice *device, gboolean stop_ppp_manager)
/* TODO: cancel SimpleConnect() if any */
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
NM_MODEM_CLASS(nm_modem_ofono_parent_class)
->deactivate_cleanup(modem, device, stop_ppp_manager);
@@ -734,13 +734,13 @@ handle_settings(GVariant *v_dict, gpointer user_data)
{
NMModemOfono * self = NM_MODEM_OFONO(user_data);
NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- NMPlatformIP4Address addr;
+ char sbuf[sizeof(_nm_utils_to_string_buffer)];
+ NMPlatformIP4Address address;
gboolean ret = FALSE;
const char * interface;
const char * s;
- const char ** array, **iter;
+ const char ** array;
guint32 address_network, gateway_network;
- guint32 ip4_route_table, ip4_route_metric;
int ifindex;
GError * error = NULL;
@@ -773,12 +773,13 @@ handle_settings(GVariant *v_dict, gpointer user_data)
}
ifindex = nm_modem_get_ip_ifindex(NM_MODEM(self));
- nm_assert(ifindex > 0);
+ g_return_if_fail(ifindex > 0);
- /* TODO: verify handling of ip4_config; check other places it's used... */
- g_clear_object(&priv->ip4_config);
+ /* TODO: verify handling of l3cd_4; check other places it's used... */
+ nm_clear_l3cd(&priv->l3cd_4);
- priv->ip4_config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex);
+ priv->l3cd_4 = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), ifindex);
+ nm_l3_config_data_set_source(priv->l3cd_4, NM_IP_CONFIG_SOURCE_WWAN);
if (!g_variant_lookup(v_dict, "Address", "&s", &s)) {
_LOGW("Settings 'Address' missing");
@@ -788,10 +789,12 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("can't convert 'Address' %s to addr", s ?: "");
goto out;
}
- memset(&addr, 0, sizeof(addr));
- addr.ifindex = ifindex;
- addr.address = address_network;
- addr.addr_source = NM_IP_CONFIG_SOURCE_WWAN;
+
+ address = (NMPlatformIP4Address){
+ .ifindex = ifindex,
+ .address = address_network,
+ .addr_source = NM_IP_CONFIG_SOURCE_WWAN,
+ };
if (!g_variant_lookup(v_dict, "Netmask", "&s", &s)) {
_LOGW("Settings 'Netmask' missing");
@@ -801,10 +804,10 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("invalid 'Netmask': %s", s ?: "");
goto out;
}
- addr.plen = nm_utils_ip4_netmask_to_prefix(address_network);
+ address.plen = nm_utils_ip4_netmask_to_prefix(address_network);
- _LOGI("Address: %s", nm_platform_ip4_address_to_string(&addr, NULL, 0));
- nm_ip4_config_add_address(priv->ip4_config, &addr);
+ _LOGI("Address: %s", nm_platform_ip4_address_to_string(&address, sbuf, sizeof(sbuf)));
+ nm_l3_config_data_add_address_4(priv->l3cd_4, &address);
if (!g_variant_lookup(v_dict, "Gateway", "&s", &s) || !s) {
_LOGW("Settings 'Gateway' missing");
@@ -814,17 +817,18 @@ handle_settings(GVariant *v_dict, gpointer user_data)
_LOGW("invalid 'Gateway': %s", s);
goto out;
}
- nm_modem_get_route_parameters(NM_MODEM(self), &ip4_route_table, &ip4_route_metric, NULL, NULL);
{
const NMPlatformIP4Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_WWAN,
.gateway = gateway_network,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
_LOGI("Gateway: %s", s);
- nm_ip4_config_add_route(priv->ip4_config, &r, NULL);
+ nm_l3_config_data_add_route_4(priv->l3cd_4, &r);
}
if (!g_variant_lookup(v_dict, "DomainNameServers", "^a&s", &array)) {
@@ -832,52 +836,49 @@ handle_settings(GVariant *v_dict, gpointer user_data)
goto out;
}
if (array) {
- for (iter = array; *iter; iter++) {
- if (nm_utils_parse_inaddr_bin(AF_INET, *iter, NULL, &address_network)
- && address_network) {
- _LOGI("DNS: %s", *iter);
- nm_ip4_config_add_nameserver(priv->ip4_config, address_network);
- } else {
- _LOGW("invalid NameServer: %s", *iter);
+ gs_free const char **array_free = array;
+ gboolean any_good = FALSE;
+
+ for (; array[0]; array++) {
+ if (!nm_utils_parse_inaddr_bin(AF_INET, *array, NULL, &address_network)
+ || !address_network) {
+ _LOGW("invalid NameServer: %s", *array);
+ continue;
}
+ any_good = TRUE;
+ _LOGI("DNS: %s", *array);
+ nm_l3_config_data_add_nameserver(priv->l3cd_4, AF_INET, &address_network);
}
-
- if (iter == array) {
+ if (!any_good) {
_LOGW("Settings: 'DomainNameServers': none specified");
- g_free(array);
goto out;
}
- g_free(array);
}
if (g_variant_lookup(v_dict, "MessageProxy", "&s", &s)) {
_LOGI("MessageProxy: %s", s);
if (s && nm_utils_parse_inaddr_bin(AF_INET, s, NULL, &address_network)) {
- nm_modem_get_route_parameters(NM_MODEM(self),
- &ip4_route_table,
- &ip4_route_metric,
- NULL,
- NULL);
-
- {
- const NMPlatformIP4Route mms_route = {
- .network = address_network,
- .plen = 32,
- .gateway = gateway_network,
- .table_coerced = nm_platform_route_table_coerce(ip4_route_table),
- .metric = ip4_route_metric,
- };
-
- nm_ip4_config_add_route(priv->ip4_config, &mms_route, NULL);
- }
- } else {
+ const NMPlatformIP4Route mms_route = {
+ .network = address_network,
+ .plen = 32,
+ .gateway = gateway_network,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
+ };
+
+ nm_l3_config_data_add_route_4(priv->l3cd_4, &mms_route);
+ } else
_LOGW("invalid MessageProxy: %s", s);
- }
}
ret = TRUE;
out:
+ if (priv->l3cd_4)
+ nm_l3_config_data_seal(priv->l3cd_4);
+
if (nm_modem_get_state(NM_MODEM(self)) != NM_MODEM_STATE_CONNECTED) {
_LOGI("emitting PREPARE_RESULT: %s", ret ? "TRUE" : "FALSE");
nm_modem_emit_prepare_result(NM_MODEM(self),
@@ -917,20 +918,19 @@ static_stage3_ip4_config_start(NMModem * modem,
NMActRequest * req,
NMDeviceStateReason *out_failure_reason)
{
- NMModemOfono * self = NM_MODEM_OFONO(modem);
- NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- GError * error = NULL;
+ NMModemOfono * self = NM_MODEM_OFONO(modem);
+ NMModemOfonoPrivate *priv = NM_MODEM_OFONO_GET_PRIVATE(self);
- if (!priv->ip4_config) {
+ if (!priv->l3cd_4) {
_LOGD("IP4 config not ready(?)");
return NM_ACT_STAGE_RETURN_FAILURE;
}
_LOGD("IP4 config is done; setting modem_state -> CONNECTED");
- g_signal_emit_by_name(self, NM_MODEM_IP4_CONFIG_RESULT, priv->ip4_config, error);
- /* Signal listener takes ownership of the IP4Config */
- priv->ip4_config = NULL;
+ nm_modem_emit_signal_new_config(NM_MODEM(self), AF_INET, priv->l3cd_4, FALSE, NULL, NULL);
+
+ nm_clear_l3cd(&priv->l3cd_4);
nm_modem_set_state(NM_MODEM(self),
NM_MODEM_STATE_CONNECTED,
@@ -1040,7 +1040,7 @@ context_proxy_new_cb(GObject *source, GAsyncResult *result, gpointer user_data)
* clear it so that we can gate getting the IP config from oFono
* on whether or not we have already received them
*/
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
/* We need to directly query ConnectionContextinteface to get the current
* property values */
@@ -1258,7 +1258,7 @@ dispose(GObject *object)
priv->connect_properties = NULL;
}
- g_clear_object(&priv->ip4_config);
+ nm_clear_l3cd(&priv->l3cd_4);
if (priv->modem_proxy) {
g_signal_handlers_disconnect_by_data(priv->modem_proxy, self);
diff --git a/src/core/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c
index 15baa677ca..a2c286c024 100644
--- a/src/core/devices/wwan/nm-modem.c
+++ b/src/core/devices/wwan/nm-modem.c
@@ -20,8 +20,7 @@
#include "devices/nm-device-private.h"
#include "nm-netns.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "ppp/nm-ppp-manager-call.h"
#include "ppp/nm-ppp-status.h"
@@ -45,8 +44,7 @@ enum {
PPP_STATS,
PPP_FAILED,
PREPARE_RESULT,
- IP4_CONFIG_RESULT,
- IP6_CONFIG_RESULT,
+ NEW_CONFIG,
AUTH_REQUESTED,
AUTH_RESULT,
REMOVED,
@@ -67,18 +65,17 @@ typedef struct _NMModemPrivate {
* We should rework the code that it's not necessary */
char *ip_iface;
- int ip_ifindex;
- NMModemIPMethod ip4_method;
- NMModemIPMethod ip6_method;
- NMUtilsIPv6IfaceId iid;
- NMModemState state;
- NMModemState prev_state; /* revert to this state if enable/disable fails */
- char * device_id;
- char * sim_id;
- NMModemIPType ip_types;
- char * sim_operator_id;
- char * operator_code;
- char * apn;
+ int ip_ifindex;
+ NMModemIPMethod ip4_method;
+ NMModemIPMethod ip6_method;
+ NMModemState state;
+ NMModemState prev_state; /* revert to this state if enable/disable fails */
+ char * device_id;
+ char * sim_id;
+ NMModemIPType ip_types;
+ char * sim_operator_id;
+ char * operator_code;
+ char * apn;
NMPPPManager *ppp_manager;
@@ -88,11 +85,6 @@ typedef struct _NMModemPrivate {
guint mm_ip_timeout;
- guint32 ip4_route_table;
- guint32 ip4_route_metric;
- guint32 ip6_route_table;
- guint32 ip6_route_metric;
-
/* PPP stats */
guint32 in_bytes;
guint32 out_bytes;
@@ -180,6 +172,41 @@ nm_modem_state_to_string(NMModemState state)
/*****************************************************************************/
+void
+nm_modem_emit_signal_new_config(NMModem * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error)
+{
+ nm_assert(NM_IS_MODEM(self));
+ nm_assert_addr_family(addr_family);
+ nm_assert(!l3cd || NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert(!do_slaac || addr_family == AF_INET6);
+ nm_assert(!iid || addr_family == AF_INET6);
+ nm_assert(!error || (!l3cd && !do_slaac && !iid));
+
+ if (error) {
+ do_slaac = FALSE;
+ l3cd = NULL;
+ iid = NULL;
+ goto out_emit;
+ }
+
+ if (addr_family == AF_INET6) {
+ do_slaac = !!do_slaac;
+ } else {
+ iid = NULL;
+ do_slaac = FALSE;
+ }
+ if (l3cd)
+ nm_l3_config_data_seal(l3cd);
+
+out_emit:
+ g_signal_emit(self, signals[NEW_CONFIG], 0, addr_family, l3cd, do_slaac, iid, error);
+}
+
gboolean
nm_modem_is_claimed(NMModem *self)
{
@@ -523,66 +550,73 @@ ppp_ifindex_set(NMPPPManager *ppp_manager, int ifindex, const char *iface, gpoin
}
static void
-ppp_ip4_config(NMPPPManager *ppp_manager, NMIP4Config *config, gpointer user_data)
+ppp_new_config(NMPPPManager * ppp_manager,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid,
+ gpointer user_data)
{
- NMModem *self = NM_MODEM(user_data);
- guint32 i, num;
- guint32 bad_dns1 = htonl(0x0A0B0C0D);
- guint32 good_dns1 = htonl(0x04020201); /* GTE nameserver */
- guint32 bad_dns2 = htonl(0x0A0B0C0E);
- guint32 good_dns2 = htonl(0x04020202); /* GTE nameserver */
- gboolean dns_workaround = FALSE;
-
- /* Work around a PPP bug (#1732) which causes many mobile broadband
- * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
- * Apparently fixed in ppp-2.4.5 but we've had some reports that this is
- * not the case.
- *
- * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6
- * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e
- */
-
- num = nm_ip4_config_get_num_nameservers(config);
- if (num == 2) {
- gboolean found1 = FALSE, found2 = FALSE;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd_modified = NULL;
+ NMModem * self = NM_MODEM(user_data);
+ gboolean do_slaac = FALSE;
- for (i = 0; i < num; i++) {
- guint32 ns = nm_ip4_config_get_nameserver(config, i);
+ nm_assert_addr_family(addr_family);
- if (ns == bad_dns1)
- found1 = TRUE;
- else if (ns == bad_dns2)
- found2 = TRUE;
+ if (addr_family == AF_INET6) {
+ if (!l3cd)
+ do_slaac = TRUE;
+ else {
+ do_slaac = !!nm_l3_config_data_get_first_obj(l3cd,
+ NMP_OBJECT_TYPE_IP6_ADDRESS,
+ nmp_object_ip6_address_is_not_link_local);
+ }
+ } else {
+ nm_assert(!iid);
+ iid = NULL;
+
+ if (l3cd) {
+ const in_addr_t bad_dns1 = htonl(0x0A0B0C0D);
+ const in_addr_t good_dns1 = htonl(0x04020201); /* GTE nameserver */
+ const in_addr_t bad_dns2 = htonl(0x0A0B0C0E);
+ const in_addr_t good_dns2 = htonl(0x04020202); /* GTE nameserver */
+ gboolean dns_workaround = FALSE;
+ const in_addr_t *addrs;
+ guint num;
+
+ /* Work around a PPP bug (#1732) which causes many mobile broadband
+ * providers to return 10.11.12.13 and 10.11.12.14 for the DNS servers.
+ * Apparently fixed in ppp-2.4.5 but we've had some reports that this is
+ * not the case.
+ *
+ * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=2e09ef6886bbf00bc5a9a641110f801e372ffde6
+ * http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=f8191bf07df374f119a07910a79217c7618f113e
+ */
+
+ addrs = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &num);
+ if (num == 0)
+ dns_workaround = TRUE;
+ else if (num == 2) {
+ /* Be somewhat conservative about substitutions; the "bad" nameservers
+ * could actually be valid in some cases, so only substitute if ppp
+ * returns *only* the two bad nameservers.
+ */
+ dns_workaround = (addrs[0] == bad_dns1 && addrs[1] == bad_dns2)
+ || (addrs[1] == bad_dns1 && addrs[0] == bad_dns2);
+ } else
+ dns_workaround = FALSE;
+
+ if (dns_workaround) {
+ _LOGW("compensating for invalid PPP-provided nameservers");
+ l3cd_modified = nm_l3_config_data_new_clone(l3cd, 0);
+ nm_l3_config_data_clear_nameservers(l3cd_modified, AF_INET);
+ nm_l3_config_data_add_nameserver(l3cd_modified, AF_INET, &good_dns1);
+ nm_l3_config_data_add_nameserver(l3cd_modified, AF_INET, &good_dns2);
+ l3cd = nm_l3_config_data_seal(l3cd_modified);
+ }
}
-
- /* Be somewhat conservative about substitutions; the "bad" nameservers
- * could actually be valid in some cases, so only substitute if ppp
- * returns *only* the two bad nameservers.
- */
- dns_workaround = (found1 && found2);
- }
-
- if (!num || dns_workaround) {
- _LOGW("compensating for invalid PPP-provided nameservers");
- nm_ip4_config_reset_nameservers(config);
- nm_ip4_config_add_nameserver(config, good_dns1);
- nm_ip4_config_add_nameserver(config, good_dns2);
}
- g_signal_emit(self, signals[IP4_CONFIG_RESULT], 0, config, NULL);
-}
-
-static void
-ppp_ip6_config(NMPPPManager * ppp_manager,
- const NMUtilsIPv6IfaceId *iid,
- NMIP6Config * config,
- gpointer user_data)
-{
- NMModem *self = NM_MODEM(user_data);
-
- NM_MODEM_GET_PRIVATE(self)->iid = *iid;
-
- nm_modem_emit_ip6_config_result(self, config, NULL);
+ nm_modem_emit_signal_new_config(self, addr_family, l3cd, do_slaac, iid, NULL);
}
static void
@@ -679,14 +713,6 @@ ppp_stage3_ip_config_start(NMModem * self,
priv->ppp_manager = nm_ppp_manager_create(priv->data_port, &error);
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-
if (!priv->ppp_manager
|| !nm_ppp_manager_start(priv->ppp_manager,
req,
@@ -710,12 +736,8 @@ ppp_stage3_ip_config_start(NMModem * self,
G_CALLBACK(ppp_ifindex_set),
self);
g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_CALLBACK(ppp_ip4_config),
- self);
- g_signal_connect(priv->ppp_manager,
- NM_PPP_MANAGER_SIGNAL_IP6_CONFIG,
- G_CALLBACK(ppp_ip6_config),
+ NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
+ G_CALLBACK(ppp_new_config),
self);
g_signal_connect(priv->ppp_manager, NM_PPP_MANAGER_SIGNAL_STATS, G_CALLBACK(ppp_stats), self);
@@ -748,8 +770,6 @@ nm_modem_stage3_ip4_config_start(NMModem * self,
connection = nm_act_request_get_applied_connection(req);
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
- nm_modem_set_route_parameters_from_device(self, device);
-
method = nm_utils_get_ip_config_method(connection, AF_INET);
/* Only Disabled and Auto methods make sense for WWAN */
@@ -788,7 +808,9 @@ nm_modem_stage3_ip4_config_start(NMModem * self,
void
nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config)
{
- NMModemPrivate *priv = NM_MODEM_GET_PRIVATE(modem);
+ //XXX
+#if 0
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (modem);
/* If the modem has an ethernet-type data interface (ie, not PPP and thus
* not point-to-point) and IP config has a /32 prefix, then we assume that
@@ -805,40 +827,11 @@ nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config)
IFF_NOARP,
TRUE);
}
+#endif
}
/*****************************************************************************/
-void
-nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error)
-{
- NMModemPrivate * priv = NM_MODEM_GET_PRIVATE(self);
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *addr;
- gboolean do_slaac = TRUE;
-
- if (error) {
- g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, NULL, FALSE, error);
- return;
- }
-
- if (config) {
- /* If the IPv6 configuration only included a Link-Local address, then
- * we have to run SLAAC to get the full IPv6 configuration.
- */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, config, &addr) {
- if (IN6_IS_ADDR_LINKLOCAL(&addr->address)) {
- if (!priv->iid.id)
- priv->iid.id = ((guint64 *) (&addr->address.s6_addr))[1];
- } else
- do_slaac = FALSE;
- }
- }
- g_assert(config || do_slaac);
-
- g_signal_emit(self, signals[IP6_CONFIG_RESULT], 0, config, do_slaac, NULL);
-}
-
static NMActStageReturn
stage3_ip6_config_request(NMModem *self, NMDeviceStateReason *out_failure_reason)
{
@@ -865,8 +858,6 @@ nm_modem_stage3_ip6_config_start(NMModem * self,
connection = nm_act_request_get_applied_connection(req);
g_return_val_if_fail(connection, NM_ACT_STAGE_RETURN_FAILURE);
- nm_modem_set_route_parameters_from_device(self, device);
-
method = nm_utils_get_ip_config_method(connection, AF_INET6);
/* Only Ignore, Disabled and Auto methods make sense for WWAN */
@@ -1539,82 +1530,6 @@ nm_modem_owns_port(NMModem *self, const char *iface)
return NM_IN_STRSET(iface, priv->ip_iface, priv->data_port, priv->control_port);
}
-gboolean
-nm_modem_get_iid(NMModem *self, NMUtilsIPv6IfaceId *out_iid)
-{
- g_return_val_if_fail(NM_IS_MODEM(self), FALSE);
-
- *out_iid = NM_MODEM_GET_PRIVATE(self)->iid;
- return TRUE;
-}
-
-/*****************************************************************************/
-
-void
-nm_modem_get_route_parameters(NMModem *self,
- guint32 *out_ip4_route_table,
- guint32 *out_ip4_route_metric,
- guint32 *out_ip6_route_table,
- guint32 *out_ip6_route_metric)
-{
- NMModemPrivate *priv;
-
- g_return_if_fail(NM_IS_MODEM(self));
-
- priv = NM_MODEM_GET_PRIVATE(self);
- NM_SET_OUT(out_ip4_route_table, priv->ip4_route_table);
- NM_SET_OUT(out_ip4_route_metric, priv->ip4_route_metric);
- NM_SET_OUT(out_ip6_route_table, priv->ip6_route_table);
- NM_SET_OUT(out_ip6_route_metric, priv->ip6_route_metric);
-}
-
-void
-nm_modem_set_route_parameters(NMModem *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
-{
- NMModemPrivate *priv;
-
- g_return_if_fail(NM_IS_MODEM(self));
-
- priv = NM_MODEM_GET_PRIVATE(self);
- if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric
- || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) {
- priv->ip4_route_table = ip4_route_table;
- priv->ip4_route_metric = ip4_route_metric;
- priv->ip6_route_table = ip6_route_table;
- priv->ip6_route_metric = ip6_route_metric;
-
- _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-
- if (priv->ppp_manager) {
- nm_ppp_manager_set_route_parameters(priv->ppp_manager,
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
-}
-
-void
-nm_modem_set_route_parameters_from_device(NMModem *self, NMDevice *device)
-{
- g_return_if_fail(NM_IS_DEVICE(device));
-
- nm_modem_set_route_parameters(self,
- nm_device_get_route_table(device, AF_INET),
- nm_device_get_route_metric(device, AF_INET),
- nm_device_get_route_table(device, AF_INET6),
- nm_device_get_route_metric(device, AF_INET6));
-}
-
/*****************************************************************************/
void
@@ -1768,10 +1683,6 @@ nm_modem_init(NMModem *self)
priv = self->_priv;
priv->ip_ifindex = -1;
- priv->ip4_route_table = RT_TABLE_MAIN;
- priv->ip4_route_metric = 700;
- priv->ip6_route_table = RT_TABLE_MAIN;
- priv->ip6_route_metric = 700;
}
static void
@@ -1945,43 +1856,27 @@ nm_modem_class_init(NMModemClass *klass)
1,
G_TYPE_UINT);
- signals[IP4_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP4_CONFIG_RESULT,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_POINTER);
-
- /**
- * NMModem::ip6-config-result:
- * @modem: the #NMModem on which the signal is emitted
- * @config: the #NMIP6Config to apply to the modem's data port
- * @do_slaac: %TRUE if IPv6 SLAAC should be started
- * @error: a #GError if any error occurred during IP configuration
- *
- * This signal is emitted when IPv6 configuration has completed or failed.
- * If @error is set the configuration failed. If @config is set, then
+ /*
+ * This signal is emitted when IP configuration has completed or failed.
+ * If @error is set the configuration failed. If @l3cd is set, then
* the details should be applied to the data port before any further
- * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC
- * should be started after applying @config to the data port.
+ * configuration (like SLAAC) is done. @do_slaac indicates whether SLAAC
+ * should be started after applying @l3cd to the data port.
*/
- signals[IP6_CONFIG_RESULT] = g_signal_new(NM_MODEM_IP6_CONFIG_RESULT,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 3,
- G_TYPE_OBJECT,
- G_TYPE_BOOLEAN,
- G_TYPE_POINTER);
+ signals[NEW_CONFIG] = g_signal_new(NM_MODEM_NEW_CONFIG,
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_INT, /* int addr_family */
+ G_TYPE_POINTER, /* const NML3ConfigData *l3cd */
+ G_TYPE_BOOLEAN, /* gboolean do_slaac */
+ G_TYPE_POINTER, /* const NMUtilsIPv6IfaceId *iid */
+ G_TYPE_POINTER); /* GError *error */
signals[PREPARE_RESULT] = g_signal_new(NM_MODEM_PREPARE_RESULT,
G_OBJECT_CLASS_TYPE(object_class),
diff --git a/src/core/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h
index 87162cfca7..a56f7b8bac 100644
--- a/src/core/devices/wwan/nm-modem.h
+++ b/src/core/devices/wwan/nm-modem.h
@@ -32,15 +32,14 @@
#define NM_MODEM_APN "apn"
/* Signals */
-#define NM_MODEM_PPP_STATS "ppp-stats"
-#define NM_MODEM_PPP_FAILED "ppp-failed"
-#define NM_MODEM_PREPARE_RESULT "prepare-result"
-#define NM_MODEM_IP4_CONFIG_RESULT "ip4-config-result"
-#define NM_MODEM_IP6_CONFIG_RESULT "ip6-config-result"
-#define NM_MODEM_AUTH_REQUESTED "auth-requested"
-#define NM_MODEM_AUTH_RESULT "auth-result"
-#define NM_MODEM_REMOVED "removed"
-#define NM_MODEM_STATE_CHANGED "state-changed"
+#define NM_MODEM_PPP_STATS "ppp-stats"
+#define NM_MODEM_PPP_FAILED "ppp-failed"
+#define NM_MODEM_PREPARE_RESULT "prepare-result"
+#define NM_MODEM_NEW_CONFIG "new-config"
+#define NM_MODEM_AUTH_REQUESTED "auth-requested"
+#define NM_MODEM_AUTH_RESULT "auth-result"
+#define NM_MODEM_REMOVED "removed"
+#define NM_MODEM_STATE_CHANGED "state-changed"
typedef enum {
NM_MODEM_IP_METHOD_UNKNOWN = 0,
@@ -161,7 +160,6 @@ const char *nm_modem_get_driver(NMModem *modem);
const char *nm_modem_get_device_id(NMModem *modem);
const char *nm_modem_get_sim_id(NMModem *modem);
const char *nm_modem_get_sim_operator_id(NMModem *modem);
-gboolean nm_modem_get_iid(NMModem *modem, NMUtilsIPv6IfaceId *out_iid);
const char *nm_modem_get_operator_code(NMModem *modem);
const char *nm_modem_get_apn(NMModem *modem);
@@ -188,20 +186,6 @@ gboolean nm_modem_complete_connection(NMModem * self,
NMConnection *const *existing_connections,
GError ** error);
-void nm_modem_get_route_parameters(NMModem *self,
- guint32 *out_ip4_route_table,
- guint32 *out_ip4_route_metric,
- guint32 *out_ip6_route_table,
- guint32 *out_ip6_route_metric);
-
-void nm_modem_set_route_parameters(NMModem *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric);
-
-void nm_modem_set_route_parameters_from_device(NMModem *modem, NMDevice *device);
-
NMActStageReturn nm_modem_act_stage1_prepare(NMModem * modem,
NMActRequest * req,
NMDeviceStateReason *out_failure_reason);
@@ -256,7 +240,13 @@ void nm_modem_emit_ppp_failed(NMModem *self, NMDeviceStateReason reason);
GArray *nm_modem_get_connection_ip_type(NMModem *self, NMConnection *connection, GError **error);
/* For subclasses */
-void nm_modem_emit_ip6_config_result(NMModem *self, NMIP6Config *config, GError *error);
+
+void nm_modem_emit_signal_new_config(NMModem * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ gboolean do_slaac,
+ const NMUtilsIPv6IfaceId *iid,
+ GError * error);
const char *nm_modem_ip_type_to_string(NMModemIPType ip_type);
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index 0dc21be630..2827c4e5fb 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -19,6 +19,7 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "libnm-platform/nm-platform.h"
@@ -39,8 +40,6 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
PROP_IFACE,
PROP_IFINDEX,
PROP_MULTI_IDX,
- PROP_ROUTE_METRIC,
- PROP_ROUTE_TABLE,
PROP_TIMEOUT,
PROP_UUID,
PROP_IAID,
@@ -67,8 +66,6 @@ typedef struct _NMDhcpClientPrivate {
guint watch_id;
int addr_family;
int ifindex;
- guint32 route_table;
- guint32 route_metric;
guint32 timeout;
guint32 iaid;
NMDhcpState state;
@@ -148,44 +145,6 @@ nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self)
}
guint32
-nm_dhcp_client_get_route_table(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), RT_TABLE_MAIN);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_table;
-}
-
-void
-nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_table != priv->route_table) {
- priv->route_table = route_table;
- _notify(self, PROP_ROUTE_TABLE);
- }
-}
-
-guint32
-nm_dhcp_client_get_route_metric(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), G_MAXUINT32);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_metric;
-}
-
-void
-nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_metric != priv->route_metric) {
- priv->route_metric = route_metric;
- _notify(self, PROP_ROUTE_METRIC);
- }
-}
-
-guint32
nm_dhcp_client_get_timeout(NMDhcpClient *self)
{
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
@@ -424,20 +383,22 @@ stop(NMDhcpClient *self, gboolean release)
}
void
-nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options)
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, NML3ConfigData *l3cd)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ GHashTable * options;
+
+ g_return_if_fail(NM_IS_DHCP_CLIENT(self));
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- g_return_if_fail(NM_IS_IP_CONFIG_ADDR_FAMILY(ip_config, priv->addr_family));
- g_return_if_fail(options);
- } else {
- g_return_if_fail(!ip_config);
- g_return_if_fail(!options);
- }
+ g_return_if_fail(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_return_if_fail(
+ nm_l3_config_data_get_dhcp_lease(l3cd, nm_dhcp_client_get_addr_family(self)));
+ } else
+ g_return_if_fail(!l3cd);
+
+ if (l3cd)
+ nm_l3_config_data_seal(l3cd);
if (new_state >= NM_DHCP_STATE_BOUND)
timeout_cleanup(self);
@@ -453,22 +414,31 @@ nm_dhcp_client_set_state(NMDhcpClient *self,
&& !NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED))
return;
- if (_LOGD_ENABLED()) {
- gs_free const char **keys = NULL;
- guint i, nkeys;
+ options =
+ l3cd ? nm_dhcp_lease_get_options(nm_l3_config_data_get_dhcp_lease(l3cd, priv->addr_family))
+ : NULL;
- keys = nm_utils_strdict_get_keys(options, TRUE, &nkeys);
- for (i = 0; i < nkeys; i++) {
- _LOGD("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i]));
- }
- }
+ if (_LOGD_ENABLED()) {
+ if (options) {
+ gs_free const char **keys = NULL;
+ guint nkeys;
+ guint i;
+
+ keys = nm_utils_strdict_get_keys(options, TRUE, &nkeys);
+ for (i = 0; i < nkeys; i++) {
+ _LOGD("option %-20s => '%s'",
+ keys[i],
+ (char *) g_hash_table_lookup(options, keys[i]));
+ }
- if (_LOGT_ENABLED() && priv->addr_family == AF_INET6) {
- gs_free char *event_id = NULL;
+ if (priv->addr_family == AF_INET6) {
+ gs_free char *event_id = NULL;
- event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
- if (event_id)
- _LOGT("event-id: \"%s\"", event_id);
+ event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
+ if (event_id)
+ _LOGT("event-id: \"%s\"", event_id);
+ }
+ }
}
if (_LOGI_ENABLED()) {
@@ -485,7 +455,7 @@ nm_dhcp_client_set_state(NMDhcpClient *self,
}
priv->state = new_state;
- g_signal_emit(G_OBJECT(self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, options);
+ g_signal_emit(G_OBJECT(self), signals[SIGNAL_STATE_CHANGED], 0, new_state, l3cd);
}
static gboolean
@@ -496,7 +466,7 @@ transaction_timeout(gpointer user_data)
priv->timeout_id = 0;
_LOGW("request timed out");
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL);
return G_SOURCE_REMOVE;
}
@@ -522,7 +492,7 @@ daemon_watch_cb(GPid pid, int status, gpointer user_data)
priv->pid = -1;
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
void
@@ -740,7 +710,7 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release)
_LOGI("canceled DHCP transaction");
nm_assert(priv->pid == -1);
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
/*****************************************************************************/
@@ -864,12 +834,11 @@ nm_dhcp_client_handle_event(gpointer unused,
const char * reason,
NMDhcpClient *self)
{
- NMDhcpClientPrivate *priv;
- guint32 old_state;
- guint32 new_state;
- gs_unref_hashtable GHashTable *str_options = NULL;
- gs_unref_object NMIPConfig *ip_config = NULL;
- NMPlatformIP6Address prefix = {
+ NMDhcpClientPrivate * priv;
+ guint32 old_state;
+ guint32 new_state;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address prefix = {
0,
};
@@ -897,9 +866,10 @@ nm_dhcp_client_handle_event(gpointer unused,
return TRUE;
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- GVariantIter iter;
- const char * name;
- GVariant * value;
+ gs_unref_hashtable GHashTable *str_options = NULL;
+ GVariantIter iter;
+ const char * name;
+ GVariant * value;
/* Copy options */
str_options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
@@ -912,14 +882,12 @@ nm_dhcp_client_handle_event(gpointer unused,
/* Create the IP config */
if (g_hash_table_size(str_options) > 0) {
if (priv->addr_family == AF_INET) {
- ip_config = NM_IP_CONFIG_CAST(
- nm_dhcp_utils_ip4_config_from_options(nm_dhcp_client_get_multi_idx(self),
- priv->ifindex,
- priv->iface,
- str_options,
- priv->route_table,
- priv->route_metric));
+ l3cd = nm_dhcp_utils_ip4_config_from_options(nm_dhcp_client_get_multi_idx(self),
+ priv->ifindex,
+ priv->iface,
+ str_options);
} else {
+<<<<<<< HEAD
prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options(
nm_dhcp_client_get_multi_idx(self),
@@ -927,9 +895,31 @@ nm_dhcp_client_handle_event(gpointer unused,
priv->iface,
str_options,
NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)));
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
+ ip_config = NM_IP_CONFIG_CAST(
+ nm_dhcp_utils_ip6_config_from_options(nm_dhcp_client_get_multi_idx(self),
+ priv->ifindex,
+ priv->iface,
+ str_options,
+ priv->info_only));
+=======
+ prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
+ l3cd = nm_dhcp_utils_ip6_config_from_options(nm_dhcp_client_get_multi_idx(self),
+ priv->ifindex,
+ priv->iface,
+ str_options,
+ priv->info_only);
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
}
} else
g_warn_if_reached();
+
+ if (l3cd) {
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd,
+ priv->addr_family,
+ g_steal_pointer(&str_options));
+ }
}
if (!IN6_IS_ADDR_UNSPECIFIED(&prefix.address)) {
@@ -937,17 +927,16 @@ nm_dhcp_client_handle_event(gpointer unused,
* of the DHCP client instance. Instead, we just signal the prefix
* to the device. */
nm_dhcp_client_emit_ipv6_prefix_delegated(self, &prefix);
- } else {
- /* Fail if no valid IP config was received */
- if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !ip_config) {
- _LOGW("client bound but IP config not received");
- new_state = NM_DHCP_STATE_FAIL;
- nm_clear_pointer(&str_options, g_hash_table_unref);
- }
+ return TRUE;
+ }
- nm_dhcp_client_set_state(self, new_state, ip_config, str_options);
+ /* Fail if no valid IP config was received */
+ if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !l3cd) {
+ _LOGW("client bound but IP config not received");
+ new_state = NM_DHCP_STATE_FAIL;
}
+ nm_dhcp_client_set_state(self, new_state, l3cd);
return TRUE;
}
@@ -1018,12 +1007,6 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
case PROP_HOSTNAME:
g_value_set_string(value, priv->hostname);
break;
- case PROP_ROUTE_METRIC:
- g_value_set_uint(value, priv->route_metric);
- break;
- case PROP_ROUTE_TABLE:
- g_value_set_uint(value, priv->route_table);
- break;
case PROP_TIMEOUT:
g_value_set_uint(value, priv->timeout);
break;
@@ -1102,12 +1085,6 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
/* construct-only */
priv->mud_url = g_value_dup_string(value);
break;
- case PROP_ROUTE_TABLE:
- priv->route_table = g_value_get_uint(value);
- break;
- case PROP_ROUTE_METRIC:
- priv->route_metric = g_value_get_uint(value);
- break;
case PROP_TIMEOUT:
/* construct-only */
priv->timeout = g_value_get_uint(value);
@@ -1300,24 +1277,6 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
NULL,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTE_TABLE] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_TABLE,
- "",
- "",
- 0,
- G_MAXUINT32,
- RT_TABLE_MAIN,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ROUTE_METRIC] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_METRIC,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY);
obj_properties[PROP_TIMEOUT] =
g_param_spec_uint(NM_DHCP_CLIENT_TIMEOUT,
@@ -1361,10 +1320,9 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
NULL,
NULL,
G_TYPE_NONE,
- 3,
+ 2,
G_TYPE_UINT,
- G_TYPE_OBJECT,
- G_TYPE_HASH_TABLE);
+ G_TYPE_POINTER /* NML3ConfigData */);
signals[SIGNAL_PREFIX_DELEGATED] = g_signal_new(NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
G_OBJECT_CLASS_TYPE(object_class),
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index e61e01de3b..4d40c57054 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -8,8 +8,6 @@
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dhcp-utils.h"
#define NM_DHCP_TIMEOUT_DEFAULT ((guint32) 45) /* default DHCP timeout, in seconds */
@@ -33,8 +31,6 @@
#define NM_DHCP_CLIENT_MULTI_IDX "multi-idx"
#define NM_DHCP_CLIENT_HOSTNAME "hostname"
#define NM_DHCP_CLIENT_MUD_URL "mud-url"
-#define NM_DHCP_CLIENT_ROUTE_METRIC "route-metric"
-#define NM_DHCP_CLIENT_ROUTE_TABLE "route-table"
#define NM_DHCP_CLIENT_TIMEOUT "timeout"
#define NM_DHCP_CLIENT_UUID "uuid"
#define NM_DHCP_CLIENT_IAID "iaid"
@@ -132,14 +128,6 @@ GBytes *nm_dhcp_client_get_hw_addr(NMDhcpClient *self);
GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self);
-guint32 nm_dhcp_client_get_route_table(NMDhcpClient *self);
-
-void nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table);
-
-guint32 nm_dhcp_client_get_route_metric(NMDhcpClient *self);
-
-void nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric);
-
guint32 nm_dhcp_client_get_timeout(NMDhcpClient *self);
guint32 nm_dhcp_client_get_iaid(NMDhcpClient *self);
@@ -190,10 +178,7 @@ void nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid);
void nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid);
-void nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options); /* str:str hash */
+void nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, NML3ConfigData *l3cd);
gboolean nm_dhcp_client_handle_event(gpointer unused,
const char * iface,
diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c
index 83de1c156d..4681be7b61 100644
--- a/src/core/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c
@@ -15,7 +15,6 @@
#include "libnm-glib-aux/nm-dedup-multi.h"
#include "nm-dhcp-utils.h"
-#include "nm-ip4-config.h"
#include "nm-utils.h"
#include "libnm-platform/nm-platform.h"
#include "NetworkManagerUtils.h"
diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c
index 2a59571cf3..31efd6d46b 100644
--- a/src/core/dhcp/nm-dhcp-manager.c
+++ b/src/core/dhcp/nm-dhcp-manager.c
@@ -45,11 +45,10 @@ G_DEFINE_TYPE(NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT)
/*****************************************************************************/
-static void client_state_changed(NMDhcpClient * client,
- NMDhcpState state,
- GObject * ip_config,
- GVariant * options,
- NMDhcpManager *self);
+static void client_state_changed(NMDhcpClient * client,
+ NMDhcpState state,
+ NML3ConfigData *l3cd,
+ NMDhcpManager * self);
/*****************************************************************************/
@@ -186,11 +185,10 @@ remove_client_unref(NMDhcpManager *self, NMDhcpClient *client)
}
static void
-client_state_changed(NMDhcpClient * client,
- NMDhcpState state,
- GObject * ip_config,
- GVariant * options,
- NMDhcpManager *self)
+client_state_changed(NMDhcpClient * client,
+ NMDhcpState state,
+ NML3ConfigData *l3cd,
+ NMDhcpManager * self)
{
if (state >= NM_DHCP_STATE_TIMEOUT)
remove_client_unref(self, client);
@@ -205,8 +203,6 @@ client_start(NMDhcpManager * self,
GBytes * hwaddr,
GBytes * bcast_hwaddr,
const char * uuid,
- guint32 route_table,
- guint32 route_metric,
const struct in6_addr * ipv6_ll_addr,
GBytes * dhcp_client_id,
gboolean enforce_duid,
@@ -323,10 +319,6 @@ client_start(NMDhcpManager * self,
hostname,
NM_DHCP_CLIENT_MUD_URL,
mud_url,
- NM_DHCP_CLIENT_ROUTE_TABLE,
- (guint) route_table,
- NM_DHCP_CLIENT_ROUTE_METRIC,
- (guint) route_metric,
NM_DHCP_CLIENT_TIMEOUT,
(guint) timeout,
NM_DHCP_CLIENT_HOSTNAME_FLAGS,
@@ -405,9 +397,15 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self,
GBytes * hwaddr,
GBytes * bcast_hwaddr,
const char * uuid,
+<<<<<<< HEAD
guint32 route_table,
guint32 route_metric,
NMDhcpClientFlags client_flags,
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ guint32 route_table,
+ guint32 route_metric,
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
gboolean send_hostname,
const char * dhcp_hostname,
const char * dhcp_fqdn,
@@ -457,6 +455,7 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self,
}
}
+<<<<<<< HEAD
return client_start(
self,
AF_INET,
@@ -485,6 +484,63 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self,
vendor_class_identifier,
reject_servers,
error);
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ return client_start(self,
+ AF_INET,
+ multi_idx,
+ iface,
+ ifindex,
+ hwaddr,
+ bcast_hwaddr,
+ uuid,
+ route_table,
+ route_metric,
+ NULL,
+ dhcp_client_id,
+ FALSE,
+ 0,
+ FALSE,
+ timeout,
+ dhcp_anycast_addr,
+ hostname,
+ use_fqdn,
+ hostname_flags,
+ mud_url,
+ FALSE,
+ 0,
+ last_ip_address,
+ 0,
+ vendor_class_identifier,
+ reject_servers,
+ error);
+=======
+ return client_start(self,
+ AF_INET,
+ multi_idx,
+ iface,
+ ifindex,
+ hwaddr,
+ bcast_hwaddr,
+ uuid,
+ NULL,
+ dhcp_client_id,
+ FALSE,
+ 0,
+ FALSE,
+ timeout,
+ dhcp_anycast_addr,
+ hostname,
+ use_fqdn,
+ hostname_flags,
+ mud_url,
+ FALSE,
+ 0,
+ last_ip_address,
+ 0,
+ vendor_class_identifier,
+ reject_servers,
+ error);
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
}
/* Caller owns a reference to the NMDhcpClient on return */
@@ -495,9 +551,15 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self,
int ifindex,
const struct in6_addr * ll_addr,
const char * uuid,
+<<<<<<< HEAD
guint32 route_table,
guint32 route_metric,
NMDhcpClientFlags client_flags,
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ guint32 route_table,
+ guint32 route_metric,
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
gboolean send_hostname,
const char * dhcp_hostname,
NMDhcpHostnameFlags hostname_flags,
@@ -533,8 +595,6 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self,
NULL,
NULL,
uuid,
- route_table,
- route_metric,
ll_addr,
duid,
enforce_duid,
diff --git a/src/core/dhcp/nm-dhcp-manager.h b/src/core/dhcp/nm-dhcp-manager.h
index 8f6c62afec..2096125172 100644
--- a/src/core/dhcp/nm-dhcp-manager.h
+++ b/src/core/dhcp/nm-dhcp-manager.h
@@ -8,7 +8,6 @@
#define __NETWORKMANAGER_DHCP_MANAGER_H__
#include "nm-dhcp-client.h"
-#include "nm-ip4-config.h"
#include "nm-dhcp-config.h"
#define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type())
@@ -39,9 +38,15 @@ NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager,
GBytes * hwaddr,
GBytes * bcast_hwaddr,
const char * uuid,
+<<<<<<< HEAD
guint32 route_table,
guint32 route_metric,
NMDhcpClientFlags client_flags,
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ guint32 route_table,
+ guint32 route_metric,
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
gboolean send_hostname,
const char * dhcp_hostname,
const char * dhcp_fqdn,
@@ -61,9 +66,15 @@ NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager,
int ifindex,
const struct in6_addr * ll_addr,
const char * uuid,
+<<<<<<< HEAD
guint32 route_table,
guint32 route_metric,
NMDhcpClientFlags client_flags,
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ guint32 route_table,
+ guint32 route_metric,
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
gboolean send_hostname,
const char * dhcp_hostname,
NMDhcpHostnameFlags hostname_flags,
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index c1a26eca62..7841153445 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "libnm-glib-aux/nm-str-buf.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "nm-dhcp-utils.h"
@@ -151,7 +152,7 @@ lease_option_consume_route(const uint8_t **datap,
static gboolean
lease_parse_address(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
GError ** error)
{
@@ -256,23 +257,23 @@ lease_parse_address(NDhcp4ClientLease *lease,
a_next_server.s_addr);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = a_timestamp,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = a_timestamp,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
return TRUE;
}
static void
lease_parse_address_list(NDhcp4ClientLease * lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
NMDhcpOptionDhcp4Options option,
GHashTable * options,
NMStrBuf * sbuf)
@@ -304,13 +305,13 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr);
break;
case NM_DHCP_OPTION_DHCP4_NIS_SERVERS:
- nm_ip4_config_add_nis_server(ip4_config, addr);
+ nm_l3_config_data_add_nis_server(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER:
- nm_ip4_config_add_wins(ip4_config, addr);
+ nm_l3_config_data_add_wins(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NTP_SERVER:
break;
@@ -324,10 +325,8 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
static void
lease_parse_routes(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
NMStrBuf * sbuf)
{
char dest_str[NM_UTILS_INET_ADDRSTRLEN];
@@ -336,9 +335,9 @@ lease_parse_routes(NDhcp4ClientLease *lease,
in_addr_t gateway;
uint8_t plen;
guint32 m;
- gboolean has_router_from_classless = FALSE;
- gboolean has_classless = FALSE;
- guint32 default_route_metric = route_metric;
+ gboolean has_router_from_classless = FALSE;
+ gboolean has_classless = FALSE;
+ guint32 default_route_metric_offset = 0;
const guint8 *l_data;
gsize l_data_len;
int r;
@@ -362,26 +361,22 @@ lease_parse_routes(NDhcp4ClientLease *lease,
if (plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
- } else {
- m = route_metric;
- }
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ } else
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -416,17 +411,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
continue;
}
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = route_metric,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -460,19 +455,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -483,7 +476,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
}
static void
-lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options)
+lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options)
{
gs_strfreev char **domains = NULL;
const guint8 * l_data;
@@ -501,7 +494,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
return;
for (i = 0; domains[i]; i++)
- nm_ip4_config_add_search(ip4_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, domains[i]);
nm_dhcp_option_take_option(options,
AF_INET,
@@ -536,34 +529,33 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options)
}
}
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
NDhcp4ClientLease *lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const guint8 * l_data;
gsize l_data_len;
const char * v_str;
guint16 v_u16;
- gboolean v_bool;
in_addr_t v_inaddr;
struct in_addr v_inaddr_s;
int r;
g_return_val_if_fail(lease != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- options = nm_dhcp_option_create_options_dict();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex);
+
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_DHCP);
+
+ options = nm_dhcp_option_create_options_dict();
- if (!lease_parse_address(lease, ip4_config, options, error))
+ if (!lease_parse_address(lease, l3cd, options, error))
return NULL;
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
@@ -582,13 +574,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_inaddr);
}
- lease_parse_routes(lease, ip4_config, options, route_table, route_metric, &sbuf);
+ lease_parse_routes(lease, l3cd, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -613,7 +601,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_str_buf_append_required_delimiter(&sbuf, ' ');
nm_str_buf_append(&sbuf, s);
- nm_ip4_config_add_domain(ip4_config, s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, s);
}
}
@@ -625,18 +613,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_search_domains(lease, ip4_config, options);
+ lease_parse_search_domains(lease, l3cd, options);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
- nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, v_u16);
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &l_data, &l_data_len);
- v_bool =
- (r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, v_bool);
+ if ((r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &l_data, &l_data_len);
if (r == 0) {
@@ -647,7 +634,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -694,21 +681,20 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str);
- nm_ip4_config_set_nis_domain(ip4_config, v_str);
+ nm_l3_config_data_set_nis_domain(l3cd, v_str);
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options, &sbuf);
lease_parse_private_options(lease, options);
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -740,36 +726,30 @@ lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_fil
static void
bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
{
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- GError * error = NULL;
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ GError * error = NULL;
_LOGT("lease available (%s)", extended ? "extended" : "new");
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
- _LOGW("%s", error->message);
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ &error);
+ if (!l3cd) {
+ _LOGW("failure to parse lease: %s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
lease_save(self, lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static void
@@ -804,10 +784,10 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
break;
case N_DHCP4_CLIENT_EVENT_RETRACTED:
case N_DHCP4_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL);
break;
case N_DHCP4_CLIENT_EVENT_CANCELLED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
break;
case N_DHCP4_CLIENT_EVENT_GRANTED:
priv->lease = n_dhcp4_client_lease_ref(event->granted.lease);
@@ -859,13 +839,12 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data)
*/
_LOGE("error %d dispatching events", r);
nm_clear_g_source_inst(&priv->event_source);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return G_SOURCE_REMOVE;
}
- while (!n_dhcp4_client_pop_event(priv->client, &event) && event) {
+ while (!n_dhcp4_client_pop_event(priv->client, &event) && event)
dhcp4_event_handle(self, event);
- }
return G_SOURCE_CONTINUE;
}
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index 5b06c65dba..a6d6dae819 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "nm-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "nm-core-utils.h"
@@ -70,18 +71,15 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
/*****************************************************************************/
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp_lease * lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const struct in_addr * addr_list;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
const char * s;
@@ -92,7 +90,6 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
int i, num;
const void * data;
gsize data_len;
- gboolean metered = FALSE;
gboolean has_router_from_classless = FALSE;
gboolean has_classless_route = FALSE;
gboolean has_static_route = FALSE;
@@ -133,9 +130,11 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
return NULL;
}
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_DHCP);
+
+ options = nm_dhcp_option_create_options_dict();
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
@@ -160,16 +159,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = ts,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = ts,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
@@ -193,7 +192,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -206,7 +205,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
- nm_ip4_config_add_search(ip4_config, search_domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -224,7 +223,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* As systemd escapes such characters, split them at \\032. */
domains = g_strsplit(s, "\\032", 0);
for (d = domains; *d; d++)
- nm_ip4_config_add_domain(ip4_config, *d);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
}
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
@@ -233,9 +232,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_routes(lease, &routes);
if (num > 0) {
- nm_auto_free_gstring GString *str_classless = NULL;
- nm_auto_free_gstring GString *str_static = NULL;
- guint32 default_route_metric = route_metric;
+ nm_auto_free_gstring GString *str_classless = NULL;
+ nm_auto_free_gstring GString *str_static = NULL;
+ guint32 default_route_metric_offset = 0;
for (i = 0; i < num; i++) {
switch (sd_dhcp_route_get_option(routes[i])) {
@@ -307,25 +306,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (r_plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
} else
- m = route_metric;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = network_net,
- .plen = r_plen,
- .gateway = r_gateway.s_addr,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = network_net,
+ .plen = r_plen,
+ .gateway = r_gateway.s_addr,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .metric = m,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ }));
}
if (str_classless && str_classless->len > 0)
@@ -342,7 +338,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_router(lease, &a_router);
if (num > 0) {
- guint32 default_route_metric = route_metric;
+ guint32 default_route_metric_offset = 0;
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
@@ -368,26 +364,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = a_router[i].s_addr,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = a_router[i].s_addr,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
}
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
- nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, mtu);
}
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
@@ -422,9 +416,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
}
- if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0)
- metered = !!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, metered);
+ if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
+ if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
+ }
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
if (num > 0) {
@@ -443,8 +438,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_take_option(options, AF_INET, private_options[i].code, option_string);
}
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -452,43 +451,38 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
static void
bound4_handle(NMDhcpSystemd *self, gboolean extended)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- sd_dhcp_lease * lease = NULL;
- GError * error = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ sd_dhcp_lease * lease = NULL;
+ GError * error = NULL;
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
_LOGW("no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ &error);
+ if (!l3cd) {
_LOGW("%s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
dhcp_lease_save(lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static int
@@ -507,10 +501,10 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL);
break;
case SD_DHCP_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP_CLIENT_EVENT_RENEW:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
@@ -745,32 +739,34 @@ ip4_start(NMDhcpClient *client,
return TRUE;
}
-static NMIP6Config *
+static NML3ConfigData *
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp6_lease * lease,
gboolean info_only,
- GHashTable ** out_options,
gint32 ts,
GError ** error)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
struct in6_addr tmp_addr;
const struct in6_addr * dns;
uint32_t lft_pref, lft_valid;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
char ** domains;
const char * s;
- nm_auto_free_gstring GString *str = NULL;
+ nm_auto_free_gstring GString *str = NULL;
+ gboolean has_any_addresses = FALSE;
int num, i;
nm_assert(lease);
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_DHCP);
+
+ options = nm_dhcp_option_create_options_dict();
sd_dhcp6_lease_reset_address_iter(lease);
nm_gstring_prepare(&str);
@@ -784,15 +780,19 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
};
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_nm_utils_inet6_ntop(&tmp_addr, addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- };
- if (str->len)
+
+ has_any_addresses = TRUE;
+ }
+
+ if (str->len) {
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str);
+ }
- if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) {
+ if (!info_only && !has_any_addresses) {
g_set_error_literal(error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_FAILED,
@@ -806,7 +806,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
for (i = 0; i < num; i++) {
_nm_utils_inet6_ntop(&dns[i], addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- nm_ip6_config_add_nameserver(ip6_config, &dns[i]);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str);
}
@@ -816,7 +816,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), domains[i]);
- nm_ip6_config_add_search(ip6_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET6, domains[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str);
}
@@ -825,30 +825,31 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s);
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip6_config);
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET6, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
static void
bound6_handle(NMDhcpSystemd *self)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- gs_free_error GError *error = NULL;
- NMPlatformIP6Address prefix = {0};
- sd_dhcp6_lease * lease = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_free_error GError *error = NULL;
+ NMPlatformIP6Address prefix = {0};
+ sd_dhcp6_lease * lease = NULL;
if (sd_dhcp6_client_get_lease(priv->client6, &lease) < 0 || !lease) {
_LOGW(" no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
+<<<<<<< HEAD
ip6_config =
lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
iface,
@@ -859,17 +860,32 @@ bound6_handle(NMDhcpSystemd *self)
&options,
ts,
&error);
-
- if (!ip6_config) {
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ ip6_config = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ nm_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)),
+ &options,
+ ts,
+ &error);
+=======
+ l3cd = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ nm_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)),
+ ts,
+ &error);
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
+
+ if (!l3cd) {
_LOGW("%s", error->message);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
- NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip6_config),
- options);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_BOUND, l3cd);
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
while (!sd_dhcp6_lease_get_pd(lease,
@@ -894,11 +910,11 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
case SD_DHCP6_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index c3cbe610b1..56328100d3 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -14,6 +14,7 @@
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-dhcp-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
@@ -24,12 +25,10 @@
/*****************************************************************************/
static gboolean
-ip4_process_dhcpcd_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhcpcd_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **routes = NULL;
const char ** r;
@@ -45,10 +44,9 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
}
for (r = routes; *r; r += 2) {
- char * slash;
- NMPlatformIP4Route route;
- int rt_cidr = 32;
- guint32 rt_addr, rt_route;
+ char * slash;
+ int rt_cidr = 32;
+ guint32 rt_addr, rt_route;
slash = strchr(*r, '/');
if (slash) {
@@ -89,14 +87,18 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
*r,
rt_cidr,
*(r + 1));
- memset(&route, 0, sizeof(route));
- route.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr);
- route.plen = rt_cidr;
- route.gateway = rt_route;
- route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+
+ nm_l3_config_data_add_route_4(
+ l3cd,
+ &((const NMPlatformIP4Route){
+ .network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr),
+ .plen = rt_cidr,
+ .gateway = rt_route,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .table_any = TRUE,
+
+ }));
}
}
@@ -153,12 +155,10 @@ process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route
}
static gboolean
-ip4_process_dhclient_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhclient_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **octets = NULL;
const char *const * o;
@@ -189,9 +189,12 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
/* normal route */
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
+
+ nm_l3_config_data_add_route_4(l3cd, &route);
_LOG2I(LOGD_DHCP4,
iface,
@@ -206,17 +209,15 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
}
static gboolean
-ip4_process_classless_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_classless_routes(const char * iface,
+ GHashTable * options,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
const char *str, *p;
g_return_val_if_fail(options != NULL, FALSE);
- g_return_val_if_fail(ip4_config != NULL, FALSE);
+ g_return_val_if_fail(l3cd != NULL, FALSE);
*gwaddr = 0;
@@ -265,28 +266,14 @@ ip4_process_classless_routes(const char * iface,
if (strchr(str, '/')) {
/* dhcpcd format */
- return ip4_process_dhcpcd_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr);
}
- return ip4_process_dhclient_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr);
}
static void
-process_classful_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config)
+process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
const char ** s;
@@ -320,8 +307,10 @@ process_classful_routes(const char * iface,
// FIXME: ensure the IP address and route are sane
- memset(&route, 0, sizeof(route));
- route.network = rt_addr;
+ route = (NMPlatformIP4Route){
+ .network = rt_addr,
+ };
+
/* RFC 2132, updated by RFC 3442:
* The Static Routes option (option 33) does not provide a subnet mask
* for each route - it is assumed that the subnet mask is implicit in
@@ -333,12 +322,15 @@ process_classful_routes(const char * iface,
}
route.gateway = rt_route;
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
+
_LOG2I(LOGD_DHCP,
iface,
" static route %s",
@@ -347,7 +339,7 @@ process_classful_routes(const char * iface,
}
static void
-process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data)
+process_domain_search(int addr_family, const char *iface, const char *str, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
gs_free char * unescaped = NULL;
@@ -356,7 +348,7 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
int i;
g_return_if_fail(str != NULL);
- g_return_if_fail(add_func != NULL);
+ nm_assert(l3cd);
unescaped = g_strdup(str);
@@ -379,46 +371,44 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
searches = nm_utils_strsplit_set(unescaped, " ");
for (s = searches; searches && *s; s++) {
_LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s);
- add_func((gpointer) *s, user_data);
+ nm_l3_config_data_add_search(l3cd, addr_family, *s);
}
}
-static void
-ip4_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data);
-}
-
-NMIP4Config *
+NML3ConfigData *
nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric)
+ GHashTable * options)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- guint32 tmp_addr;
- in_addr_t addr;
- NMPlatformIP4Address address;
- char * str = NULL;
- gboolean gateway_has = FALSE;
- guint32 gateway = 0;
- guint8 plen = 0;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ guint32 tmp_addr;
+ in_addr_t addr;
+ NMPlatformIP4Address address;
+ char * str = NULL;
+ gboolean gateway_has = FALSE;
+ guint32 gateway = 0;
+ guint8 plen = 0;
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- memset(&address, 0, sizeof(address));
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_DHCP);
+
+ now = nm_utils_get_monotonic_timestamp_sec();
+
+ address = (NMPlatformIP4Address){
+ .timestamp = now,
+ };
str = g_hash_table_lookup(options, "ip_address");
- if (str && (inet_pton(AF_INET, str, &addr) > 0))
- _LOG2I(LOGD_DHCP4, iface, " address %s", str);
- else
+ if (!str || !nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &addr))
return NULL;
+ _LOG2I(LOGD_DHCP4, iface, " address %s", str);
+
str = g_hash_table_lookup(options, "subnet_mask");
if (str && (inet_pton(AF_INET, str, &tmp_addr) > 0)) {
plen = nm_utils_ip4_netmask_to_prefix(tmp_addr);
@@ -433,13 +423,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
*/
- if (!ip4_process_classless_routes(iface,
- options,
- route_table,
- route_metric,
- ip4_config,
- &gateway))
- process_classful_routes(iface, options, route_table, route_metric, ip4_config);
+ if (!ip4_process_classless_routes(iface, options, l3cd, &gateway))
+ process_classful_routes(iface, options, l3cd);
if (gateway) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf));
@@ -450,10 +435,10 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
*/
str = g_hash_table_lookup(options, "routers");
if (str) {
- gs_free const char **routers = nm_utils_strsplit_set(str, " ");
- const char ** s;
+ char **routers = g_strsplit(str, " ", 0);
+ char **s;
- for (s = routers; routers && *s; s++) {
+ for (s = routers; *s; s++) {
/* FIXME: how to handle multiple routers? */
if (inet_pton(AF_INET, *s, &gateway) > 0) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", *s);
@@ -462,6 +447,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
} else
_LOG2W(LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s);
}
+ g_strfreev(routers);
}
}
@@ -469,11 +455,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
const NMPlatformIP4Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
.gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(ip4_config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
}
str = g_hash_table_lookup(options, "dhcp_lease_time");
@@ -483,7 +471,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip4_config_add_address(ip4_config, &address);
+
+ nm_l3_config_data_add_address_4(l3cd, &address);
str = g_hash_table_lookup(options, "host_name");
if (str)
@@ -497,7 +486,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nameserver(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s);
}
} else
@@ -512,13 +501,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = domains; domains && *s; s++) {
_LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s);
- nm_ip4_config_add_domain(ip4_config, *s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *s);
}
}
str = g_hash_table_lookup(options, "domain_search");
if (str)
- process_domain_search(iface, str, ip4_add_domain_search, ip4_config);
+ process_domain_search(AF_INET, iface, str, l3cd);
str = g_hash_table_lookup(options, "netbios_name_servers");
if (str) {
@@ -528,7 +517,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nbns; nbns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_wins(ip4_config, tmp_addr);
+ nm_l3_config_data_add_wins(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s);
}
} else
@@ -546,13 +535,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
return NULL;
if (int_mtu > 576)
- nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, int_mtu);
}
str = g_hash_table_lookup(options, "nis_domain");
if (str) {
_LOG2I(LOGD_DHCP4, iface, " NIS domain '%s'", str);
- nm_ip4_config_set_nis_domain(ip4_config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
}
str = g_hash_table_lookup(options, "nis_servers");
@@ -563,7 +552,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nis; nis && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nis_server(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nis_server(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s);
}
} else
@@ -572,19 +561,14 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
str = g_hash_table_lookup(options, "vendor_encapsulated_options");
- nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED"));
+ if (str && strstr(str, "ANDROID_METERED"))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
- return g_steal_pointer(&ip4_config);
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
-static void
-ip6_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data);
-}
-
NMPlatformIP6Address
nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
{
@@ -635,25 +619,30 @@ nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
return address;
}
-NMIP6Config *
+NML3ConfigData *
nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
GHashTable * options,
gboolean info_only)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- struct in6_addr tmp_addr;
- NMPlatformIP6Address address;
- char * str = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ struct in6_addr tmp_addr;
+ NMPlatformIP6Address address;
+ char * str = NULL;
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- memset(&address, 0, sizeof(address));
- address.plen = 128;
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ now = nm_utils_get_monotonic_timestamp_sec();
+
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ .timestamp = now,
+ };
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_DHCP);
str = g_hash_table_lookup(options, "max_life");
if (str) {
@@ -676,7 +665,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
address.address = tmp_addr;
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_LOG2I(LOGD_DHCP6, iface, " address %s", str);
} else if (info_only == FALSE) {
/* No address in Managed mode is a hard error */
@@ -695,7 +684,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) {
if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
- nm_ip6_config_add_nameserver(ip6_config, &tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &tmp_addr);
_LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s);
}
} else
@@ -705,9 +694,9 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup(options, "dhcp6_domain_search");
if (str)
- process_domain_search(iface, str, ip6_add_domain_search, ip6_config);
+ process_domain_search(AF_INET6, iface, str, l3cd);
- return g_steal_pointer(&ip6_config);
+ return g_steal_pointer(&l3cd);
}
char *
@@ -838,6 +827,65 @@ nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease)
return g_strdup_printf("%s|%s", iaid, start);
}
+gboolean
+nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged)
+{
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd_merged = NULL;
+ const NMPlatformIP6Address * addr;
+ NMDhcpLease * lease_old;
+ NMDhcpLease * lease_new;
+ NMDedupMultiIter iter;
+ const char * start;
+ const char * iaid;
+
+ nm_assert(out_l3cd_merged);
+ nm_assert(!*out_l3cd_merged);
+
+ if (!l3cd_old)
+ return FALSE;
+ if (!l3cd_new)
+ return FALSE;
+
+ lease_new = nm_l3_config_data_get_dhcp_lease(l3cd_new, AF_INET6);
+ if (!lease_new)
+ return FALSE;
+
+ lease_old = nm_l3_config_data_get_dhcp_lease(l3cd_old, AF_INET6);
+ if (!lease_old)
+ return FALSE;
+
+ start = nm_dhcp_lease_lookup_option(lease_new, "life_starts");
+ if (!start)
+ return FALSE;
+ iaid = nm_dhcp_lease_lookup_option(lease_new, "iaid");
+ if (!iaid)
+ return FALSE;
+
+ if (!nm_streq0(start, nm_dhcp_lease_lookup_option(lease_old, "life_starts")))
+ return FALSE;
+ if (!nm_streq0(iaid, nm_dhcp_lease_lookup_option(lease_old, "iaid")))
+ return FALSE;
+
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
+ **/
+
+ l3cd_merged = nm_l3_config_data_new_clone(l3cd_old, -1);
+
+ nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd_new, &addr)
+ nm_l3_config_data_add_address_6(l3cd_merged, addr);
+
+ /* Note that we keep the original NMDhcpLease. All we take from the new lease are the
+ * addresses. Maybe this is not right?? */
+ nm_l3_config_data_set_dhcp_lease(l3cd_merged, AF_INET6, lease_old);
+
+ *out_l3cd_merged = nm_l3_config_data_ref_and_seal(g_steal_pointer(&l3cd_merged));
+ return TRUE;
+}
+
/*****************************************************************************/
gboolean
diff --git a/src/core/dhcp/nm-dhcp-utils.h b/src/core/dhcp/nm-dhcp-utils.h
index 69715f90fe..bee10de3f6 100644
--- a/src/core/dhcp/nm-dhcp-utils.h
+++ b/src/core/dhcp/nm-dhcp-utils.h
@@ -8,21 +8,18 @@
#include <stdlib.h>
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
-
-NMIP4Config *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric);
-
-NMIP6Config *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- gboolean info_only);
+#include "nm-l3-config-data.h"
+
+NML3ConfigData *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options);
+
+NML3ConfigData *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options,
+ gboolean info_only);
NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options);
@@ -38,6 +35,10 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family,
char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease);
+gboolean nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged);
+
/*****************************************************************************/
static inline gboolean
diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c
index e9a6209644..803933ff04 100644
--- a/src/core/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/core/dhcp/tests/test-dhcp-dhclient.c
@@ -15,7 +15,6 @@
#include "dhcp/nm-dhcp-dhclient-utils.h"
#include "dhcp/nm-dhcp-utils.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c
index 4d47e7e283..0fab5c15ad 100644
--- a/src/core/dhcp/tests/test-dhcp-utils.c
+++ b/src/core/dhcp/tests/test-dhcp-utils.c
@@ -20,20 +20,18 @@
/*****************************************************************************/
-static NMIP4Config *
-_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric)
+static const NML3ConfigData *
+_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options)
{
nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = nm_dedup_multi_index_new();
- NMIP4Config * config;
-
- config = nm_dhcp_utils_ip4_config_from_options(multi_idx,
- ifindex,
- iface,
- options,
- RT_TABLE_MAIN,
- route_metric);
- g_assert(config);
- return config;
+ NML3ConfigData * l3cd;
+
+ l3cd = nm_dhcp_utils_ip4_config_from_options(multi_idx, ifindex, iface, options);
+ g_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_assert(!nm_l3_config_data_is_sealed(l3cd));
+ if (nmtst_get_rand_bool())
+ nm_l3_config_data_seal(l3cd);
+ return l3cd;
}
typedef struct {
@@ -74,58 +72,57 @@ static const Option generic_options[] = {
static void
test_generic_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- const NMPlatformIP4Route * route;
- guint32 tmp;
- const char * expected_addr = "192.168.1.106";
- const char * expected_gw = "192.168.1.1";
- const char * expected_dns1 = "216.254.95.2";
- const char * expected_dns2 = "216.231.41.2";
- const char * expected_search1 = "foobar.com";
- const char * expected_search2 = "blah.foobar.com";
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
-
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const NMPlatformIP4Route * route;
+ guint32 tmp;
+ const char * expected_addr = "192.168.1.106";
+ const char * expected_gw = "192.168.1.1";
+ const char * expected_dns1 = "216.254.95.2";
+ const char * expected_dns2 = "216.231.41.2";
+ const char * expected_search1 = "foobar.com";
+ const char * expected_search2 = "blah.foobar.com";
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ const char *const * strarr;
+ const in_addr_t * ia_arr;
+ guint u;
+
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_addr, &tmp) > 0);
g_assert(address->address == tmp);
g_assert(address->peer_address == tmp);
g_assert_cmpint(address->plen, ==, 24);
- /* Gateway */
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
+ nmtst_assert_ip_address(AF_INET,
+ nmtst_l3_config_data_get_best_gateway(l3cd, AF_INET),
+ expected_gw);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 0);
+ g_assert(!nm_l3_config_data_get_wins(l3cd, &u));
+ g_assert_cmpint(u, ==, 0);
- g_assert_cmpint(nm_ip4_config_get_mtu(ip4_config), ==, 987);
+ g_assert_cmpint(nm_l3_config_data_get_mtu(l3cd), ==, 987);
- /* Domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 2);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search2);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ g_assert_cmpstr(strarr[0], ==, expected_search1);
+ g_assert_cmpstr(strarr[1], ==, expected_search2);
- /* DNS servers */
- g_assert_cmpint(nm_ip4_config_get_num_nameservers(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_dns1, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_dns2, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 1) == tmp);
+ ia_arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_dns1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_dns2);
- /* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
- /* Route #1 */
- route = _nmtst_ip4_config_get_route(ip4_config, 0);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_route1_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_route1_gw, &tmp) > 0);
@@ -133,69 +130,63 @@ test_generic_options(void)
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- /* Route #2 */
- route = _nmtst_ip4_config_get_route(ip4_config, 1);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 1);
g_assert(route->network == nmtst_inet4_from_string(expected_route2_dest));
g_assert(route->gateway == nmtst_inet4_from_string(expected_route2_gw));
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- route = _nmtst_ip4_config_get_route(ip4_config, 2);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 2);
g_assert(route->network == nmtst_inet4_from_string("0.0.0.0"));
g_assert(route->gateway == nmtst_inet4_from_string("192.168.1.1"));
g_assert_cmpint(route->plen, ==, 0);
g_assert_cmpint(route->metric, ==, 0);
-
- g_hash_table_destroy(options);
}
static void
test_wins_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- guint32 tmp;
- const char * expected_wins1 = "63.12.199.5";
- const char * expected_wins2 = "150.4.88.120";
- static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const char * expected_wins1 = "63.12.199.5";
+ const char * expected_wins2 = "150.4.88.120";
+ static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
{NULL, NULL}};
+ const in_addr_t * ia_arr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_wins1, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_wins2, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 1) == tmp);
- g_hash_table_destroy(options);
+ ia_arr = nm_l3_config_data_get_wins(l3cd, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_wins1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_wins2);
}
static void
test_vendor_option_metered(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"vendor_encapsulated_options", "ANDROID_METERED"}, {NULL, NULL}};
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == FALSE);
- g_hash_table_destroy(options);
- g_clear_object(&ip4_config);
-
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == TRUE);
- g_hash_table_destroy(options);
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == NM_TERNARY_DEFAULT);
+ nm_clear_pointer(&options, g_hash_table_destroy);
+ nm_clear_l3cd(&l3cd);
+
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == TRUE);
}
static void
@@ -252,18 +243,18 @@ test_parse_search_list(void)
}
static void
-ip4_test_route(NMIP4Config *ip4_config,
- guint route_num,
- const char * expected_dest,
- const char * expected_gw,
- guint expected_prefix)
+ip4_test_route(const NML3ConfigData *l3cd,
+ guint route_num,
+ const char * expected_dest,
+ const char * expected_gw,
+ guint expected_prefix)
{
const NMPlatformIP4Route *route;
guint32 tmp;
g_assert(expected_prefix <= 32);
- route = _nmtst_ip4_config_get_route(ip4_config, route_num);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, route_num);
g_assert(inet_pton(AF_INET, expected_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
@@ -272,110 +263,105 @@ ip4_test_route(NMIP4Config *ip4_config,
g_assert_cmpint(route->metric, ==, 0);
}
-static void
-ip4_test_gateway(NMIP4Config *ip4_config, const char *expected_gw)
-{
- guint32 tmp;
-
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
-}
+#define ip4_test_gateway(l3cd, expected_gw) \
+ G_STMT_START \
+ { \
+ const NML3ConfigData *_l3cd = (l3cd); \
+ \
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(_l3cd, AF_INET), ==, 1); \
+ nmtst_assert_ip_address(AF_INET, \
+ nmtst_l3_config_data_get_best_gateway(_l3cd, AF_INET), \
+ expected_gw); \
+ } \
+ G_STMT_END
static void
test_classless_static_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhclient custom format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_classless_static_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_fedora_dhclient_classless_static_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "129.210.177.128";
- const char * expected_route1_gw = "192.168.0.113";
- const char * expected_route2_dest = "2.0.0.0";
- const char * expected_route2_gw = "10.34.255.6";
- const char * expected_gateway = "192.168.0.113";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "129.210.177.128";
+ const char * expected_route1_gw = "192.168.0.113";
+ const char * expected_route2_dest = "2.0.0.0";
+ const char * expected_route2_gw = "10.34.255.6";
+ const char * expected_gateway = "192.168.0.113";
+ static const Option data[] = {
/* Fedora dhclient format */
{"classless_static_routes",
"0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 25);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 7);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 25);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 7);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
-
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhclient_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
/* dhclient format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41"},
{NULL, NULL}};
@@ -384,27 +370,25 @@ test_dhclient_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41"},
{NULL, NULL}};
@@ -413,30 +397,28 @@ test_dhcpcd_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1"},
{NULL, NULL}};
@@ -444,30 +426,28 @@ test_dhclient_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhcpcd_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1"},
{NULL, NULL}};
@@ -475,7 +455,7 @@ test_dhcpcd_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
@@ -483,22 +463,20 @@ test_dhcpcd_invalid_classless_routes_2(void)
*/
/* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41"},
{NULL, NULL}};
@@ -506,25 +484,23 @@ test_dhclient_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41"},
{NULL, NULL}};
@@ -532,133 +508,124 @@ test_dhcpcd_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*DHCP provided invalid classless static route*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhclient_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhcpcd_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_search0 = "host1";
- const char * expected_search1 = "host2";
- const char * expected_search2 = "host3";
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_search0 = "host1";
+ const char * expected_search1 = "host2";
+ const char * expected_search2 = "host3";
static const Option data[] = {{"domain_search", "host1\\032host2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 3);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search0);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 2), ==, expected_search2);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 3);
+ g_assert_cmpstr(strarr[0], ==, expected_search0);
+ g_assert_cmpstr(strarr[1], ==, expected_search1);
+ g_assert_cmpstr(strarr[2], ==, expected_search2);
}
static void
test_invalid_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"domain_search", "host1\\aahost2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
options = fill_table(generic_options, NULL);
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*invalid domain search*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 0);
-
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 0);
+ g_assert(!strarr);
}
static void
test_ip4_missing_prefix(const char *ip, guint32 expected_prefix)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
options = fill_table(generic_options, NULL);
g_hash_table_insert(options, "ip_address", (gpointer) ip);
g_hash_table_remove(options, "subnet_mask");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, expected_prefix);
-
- g_hash_table_destroy(options);
}
static void
@@ -682,9 +649,9 @@ test_ip4_missing_prefix_8(void)
static void
test_ip4_prefix_classless(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
/* Ensure that the missing-subnet-mask handler doesn't mangle classless
* subnet masks at all. The handler should trigger only if the server
@@ -695,14 +662,12 @@ test_ip4_prefix_classless(void)
g_hash_table_insert(options, "ip_address", "172.16.54.22");
g_hash_table_insert(options, "subnet_mask", "255.255.252.0");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, 22);
-
- g_hash_table_destroy(options);
}
#define COMPARE_ID(src, is_str, expected, expected_len) \
diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c
index e8697e817e..f4eea33a13 100644
--- a/src/core/dnsmasq/nm-dnsmasq-manager.c
+++ b/src/core/dnsmasq/nm-dnsmasq-manager.c
@@ -17,6 +17,7 @@
#include "nm-dnsmasq-utils.h"
#include "nm-utils.h"
#include "NetworkManagerUtils.h"
+#include "nm-l3-config-data.h"
#include "libnm-core-intern/nm-core-internal.h"
#define CONFDIR NMCONFDIR "/dnsmasq-shared.d"
@@ -85,24 +86,28 @@ dm_watch_cb(GPid pid, int status, gpointer user_data)
}
static GPtrArray *
-create_dm_cmd_line(const char * iface,
- const NMIP4Config *ip4_config,
- const char * pidfile,
- gboolean announce_android_metered,
- GError ** error)
+create_dm_cmd_line(const char * iface,
+ const NML3ConfigData *l3cd,
+ const char * pidfile,
+ gboolean announce_android_metered,
+ GError ** error)
{
gs_unref_ptrarray GPtrArray *cmd = NULL;
nm_auto_free_gstring GString *s = NULL;
char first[INET_ADDRSTRLEN];
char last[INET_ADDRSTRLEN];
char listen_address_s[INET_ADDRSTRLEN];
- char tmpaddr[INET_ADDRSTRLEN];
+ char sbuf_addr[INET_ADDRSTRLEN];
gs_free char * error_desc = NULL;
const char * dm_binary;
const NMPlatformIP4Address * listen_address;
- guint i, n;
+ const in_addr_t * ipv4arr;
+ const char *const * strarr;
+ guint n;
+ guint i;
- listen_address = nm_ip4_config_get_first_address(ip4_config);
+ listen_address = NMP_OBJECT_CAST_IP4_ADDRESS(
+ nm_l3_config_data_get_first_obj(l3cd, NMP_OBJECT_TYPE_IP4_ADDRESS, NULL));
g_return_val_if_fail(listen_address, NULL);
@@ -151,28 +156,28 @@ create_dm_cmd_line(const char * iface,
nm_strv_ptrarray_add_string_printf(cmd, "--dhcp-range=%s,%s,60m", first, last);
- if (nm_ip4_config_best_default_route_get(ip4_config)) {
+ if (nm_l3_config_data_get_best_default_route(l3cd, AF_INET)) {
nm_strv_ptrarray_add_string_concat(cmd, "--dhcp-option=option:router,", listen_address_s);
}
- if ((n = nm_ip4_config_get_num_nameservers(ip4_config))) {
+ ipv4arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &n);
+ if (n > 0) {
nm_gstring_prepare(&s);
g_string_append(s, "--dhcp-option=option:dns-server");
for (i = 0; i < n; i++) {
g_string_append_c(s, ',');
- g_string_append(
- s,
- _nm_utils_inet4_ntop(nm_ip4_config_get_nameserver(ip4_config, i), tmpaddr));
+ g_string_append(s, _nm_utils_inet4_ntop(ipv4arr[i], sbuf_addr));
}
nm_strv_ptrarray_take_gstring(cmd, &s);
}
- if ((n = nm_ip4_config_get_num_searches(ip4_config))) {
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &n);
+ if (n > 0) {
nm_gstring_prepare(&s);
g_string_append(s, "--dhcp-option=option:domain-search");
for (i = 0; i < n; i++) {
g_string_append_c(s, ',');
- g_string_append(s, nm_ip4_config_get_search(ip4_config, i));
+ g_string_append(s, strarr[i]);
}
nm_strv_ptrarray_take_gstring(cmd, &s);
}
@@ -237,25 +242,25 @@ out:
}
gboolean
-nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
- NMIP4Config * ip4_config,
- gboolean announce_android_metered,
- GError ** error)
+nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
+ const NML3ConfigData *l3cd,
+ gboolean announce_android_metered,
+ GError ** error)
{
- NMDnsMasqManagerPrivate *priv;
gs_unref_ptrarray GPtrArray *dm_cmd = NULL;
gs_free char * cmd_str = NULL;
+ NMDnsMasqManagerPrivate * priv;
g_return_val_if_fail(NM_IS_DNSMASQ_MANAGER(manager), FALSE);
g_return_val_if_fail(!error || !*error, FALSE);
- g_return_val_if_fail(nm_ip4_config_get_num_addresses(ip4_config) > 0, FALSE);
+ g_return_val_if_fail(NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
+ g_return_val_if_fail(nm_l3_config_data_get_num_addresses(l3cd, AF_INET) > 0, FALSE);
priv = NM_DNSMASQ_MANAGER_GET_PRIVATE(manager);
kill_existing_by_pidfile(priv->pidfile);
- dm_cmd =
- create_dm_cmd_line(priv->iface, ip4_config, priv->pidfile, announce_android_metered, error);
+ dm_cmd = create_dm_cmd_line(priv->iface, l3cd, priv->pidfile, announce_android_metered, error);
if (!dm_cmd)
return FALSE;
diff --git a/src/core/dnsmasq/nm-dnsmasq-manager.h b/src/core/dnsmasq/nm-dnsmasq-manager.h
index 272d1cead1..78ca37251e 100644
--- a/src/core/dnsmasq/nm-dnsmasq-manager.h
+++ b/src/core/dnsmasq/nm-dnsmasq-manager.h
@@ -6,8 +6,6 @@
#ifndef __NETWORKMANAGER_DNSMASQ_MANAGER_H__
#define __NETWORKMANAGER_DNSMASQ_MANAGER_H__
-#include "nm-ip4-config.h"
-
#define NM_TYPE_DNSMASQ_MANAGER (nm_dnsmasq_manager_get_type())
#define NM_DNSMASQ_MANAGER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DNSMASQ_MANAGER, NMDnsMasqManager))
@@ -35,10 +33,10 @@ GType nm_dnsmasq_manager_get_type(void);
NMDnsMasqManager *nm_dnsmasq_manager_new(const char *iface);
-gboolean nm_dnsmasq_manager_start(NMDnsMasqManager *manager,
- NMIP4Config * ip4_config,
- gboolean announce_android_metered,
- GError ** error);
+gboolean nm_dnsmasq_manager_start(NMDnsMasqManager * manager,
+ const NML3ConfigData *l3cd,
+ gboolean announce_android_metered,
+ GError ** error);
void nm_dnsmasq_manager_stop(NMDnsMasqManager *manager);
diff --git a/src/core/meson.build b/src/core/meson.build
index 9552f7de81..37e0e4849e 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -94,7 +94,6 @@ endif
libNetworkManager = static_library(
'NetworkManager',
sources: files(
- 'devices/nm-acd-manager.c',
'devices/nm-device-6lowpan.c',
'devices/nm-device-bond.c',
'devices/nm-device-bridge.c',
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index 736fc937d7..7009daf636 100644
--- a/src/core/ndisc/nm-ndisc.c
+++ b/src/core/ndisc/nm-ndisc.c
@@ -16,6 +16,7 @@
#include "nm-utils.h"
#include "libnm-platform/nm-platform.h"
#include "libnm-platform/nmp-netns.h"
+#include "libnm-platform/nm-platform-utils.h"
#include "nm-l3-config-data.h"
#define _NMLOG_PREFIX_NAME "ndisc"
@@ -101,8 +102,6 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
int ifindex,
const NMNDiscData * rdata,
NMSettingIP6ConfigPrivacy ip6_privacy,
- guint32 route_table,
- guint32 route_metric,
gboolean kernel_support_rta_pref,
gboolean kernel_support_extended_ifa_flags)
{
@@ -166,8 +165,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
.plen = ndisc_route->plen,
.gateway = ndisc_route->gateway,
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
.rt_pref = ndisc_route->preference,
};
nm_assert((NMIcmpv6RouterPref) r.rt_pref == ndisc_route->preference);
@@ -180,8 +181,10 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx,
NMPlatformIP6Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
.ifindex = ifindex,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
for (i = 0; i < rdata->gateways_n; i++) {
@@ -983,30 +986,85 @@ announce_router_solicited(NMNDisc *ndisc)
/*****************************************************************************/
void
-nm_ndisc_set_config(NMNDisc * ndisc,
- const GArray *addresses,
- const GArray *dns_servers,
- const GArray *dns_domains)
+nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd)
{
- gboolean changed = FALSE;
- guint i;
+ gboolean changed = FALSE;
+ const struct in6_addr *in6arr;
+ const char *const * strvarr;
+ NMDedupMultiIter iter;
+ const NMPObject * obj;
+ gint64 now_msec;
+ guint len;
+ guint i;
+
+ nm_assert(NM_IS_NDISC(ndisc));
+ nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER);
- for (i = 0; i < addresses->len; i++) {
- if (nm_ndisc_add_address(ndisc, &g_array_index(addresses, NMNDiscAddress, i), 0, FALSE))
+ now_msec = nm_utils_get_monotonic_timestamp_msec();
+
+ nm_l3_config_data_iter_obj_for_each (&iter, l3cd, &obj, NMP_OBJECT_TYPE_IP6_ADDRESS) {
+ const NMPlatformIP6Address *addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj);
+ guint32 preferred;
+ guint32 lifetime;
+ NMNDiscAddress a;
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address))
+ continue;
+
+ if (addr->n_ifa_flags & IFA_F_TENTATIVE || addr->n_ifa_flags & IFA_F_DADFAILED)
+ continue;
+
+ if (addr->plen != 64)
+ continue;
+
+ lifetime = nmp_utils_lifetime_get(addr->timestamp,
+ addr->lifetime,
+ addr->preferred,
+ NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
+ &preferred);
+ if (!lifetime)
+ continue;
+
+ a = (NMNDiscAddress){
+ .address = addr->address,
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, lifetime),
+ .expiry_preferred_msec =
+ _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, preferred),
+ };
+
+ if (nm_ndisc_add_address(ndisc, &a, now_msec, FALSE))
changed = TRUE;
}
- for (i = 0; i < dns_servers->len; i++) {
- if (nm_ndisc_add_dns_server(ndisc,
- &g_array_index(dns_servers, NMNDiscDNSServer, i),
- G_MININT64))
+ in6arr = NULL;
+ len = 0;
+ if (l3cd)
+ in6arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET6, &len);
+ for (i = 0; i < len; i++) {
+ NMNDiscDNSServer n;
+
+ n = (NMNDiscDNSServer){
+ .address = in6arr[i],
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
+ NM_NDISC_ROUTER_LIFETIME),
+ };
+ if (nm_ndisc_add_dns_server(ndisc, &n, G_MININT64))
changed = TRUE;
}
- for (i = 0; i < dns_domains->len; i++) {
- if (nm_ndisc_add_dns_domain(ndisc,
- &g_array_index(dns_domains, NMNDiscDNSDomain, i),
- G_MININT64))
+ strvarr = NULL;
+ len = 0;
+ if (l3cd)
+ strvarr = nm_l3_config_data_get_searches(l3cd, AF_INET6, &len);
+ for (i = 0; i < len; i++) {
+ NMNDiscDNSDomain n;
+
+ n = (NMNDiscDNSDomain){
+ .domain = (char *) strvarr[i],
+ .expiry_msec = _nm_ndisc_lifetime_to_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP,
+ NM_NDISC_ROUTER_LIFETIME),
+ };
+ if (nm_ndisc_add_dns_domain(ndisc, &n, G_MININT64))
changed = TRUE;
}
diff --git a/src/core/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h
index 31f736a8f0..a01ff12010 100644
--- a/src/core/ndisc/nm-ndisc.h
+++ b/src/core/ndisc/nm-ndisc.h
@@ -226,10 +226,7 @@ void nm_ndisc_start(NMNDisc *ndisc);
void nm_ndisc_stop(NMNDisc *ndisc);
NMNDiscConfigMap
nm_ndisc_dad_failed(NMNDisc *ndisc, const struct in6_addr *address, gboolean emit_changed_signal);
-void nm_ndisc_set_config(NMNDisc * ndisc,
- const GArray *addresses,
- const GArray *dns_servers,
- const GArray *dns_domains);
+void nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd);
NMPlatform *nm_ndisc_get_platform(NMNDisc *self);
NMPNetns * nm_ndisc_netns_get(NMNDisc *self);
@@ -270,8 +267,6 @@ struct _NML3ConfigData *nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_id
int ifindex,
const NMNDiscData * rdata,
NMSettingIP6ConfigPrivacy ip6_privacy,
- guint32 route_table,
- guint32 route_metric,
gboolean kernel_support_rta_pref,
gboolean kernel_support_extended_ifa_flags);
diff --git a/src/core/nm-act-request.c b/src/core/nm-act-request.c
index cb4b0260a5..b34ddefccf 100644
--- a/src/core/nm-act-request.c
+++ b/src/core/nm-act-request.c
@@ -22,8 +22,7 @@
#include "libnm-core-aux-intern/nm-auth-subject.h"
typedef struct {
- CList call_ids_lst_head;
- NMUtilsShareRules *share_rules;
+ CList call_ids_lst_head;
} NMActRequestPrivate;
struct _NMActRequest {
@@ -248,36 +247,6 @@ nm_act_request_clear_secrets(NMActRequest *self)
/*****************************************************************************/
-NMUtilsShareRules *
-nm_act_request_get_shared(NMActRequest *req)
-{
- g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE);
-
- return NM_ACT_REQUEST_GET_PRIVATE(req)->share_rules;
-}
-
-void
-nm_act_request_set_shared(NMActRequest *req, NMUtilsShareRules *rules)
-{
- NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req);
-
- g_return_if_fail(NM_IS_ACT_REQUEST(req));
-
- if (priv->share_rules == rules)
- return;
-
- if (priv->share_rules) {
- nm_utils_share_rules_apply(priv->share_rules, FALSE);
- priv->share_rules = NULL;
- }
- if (rules) {
- priv->share_rules = rules;
- nm_utils_share_rules_apply(priv->share_rules, TRUE);
- }
-}
-
-/*****************************************************************************/
-
static void
device_notify(GObject *object, GParamSpec *pspec, gpointer self)
{
@@ -506,11 +475,6 @@ dispose(GObject *object)
c_list_for_each_entry_safe (call_id, call_id_safe, &priv->call_ids_lst_head, call_ids_lst)
_do_cancel_secrets(self, call_id, TRUE);
- if (priv->share_rules) {
- nm_utils_share_rules_apply(priv->share_rules, FALSE);
- nm_clear_pointer(&priv->share_rules, nm_utils_share_rules_free);
- }
-
G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object);
}
diff --git a/src/core/nm-act-request.h b/src/core/nm-act-request.h
index 2a568430ac..698a9985a4 100644
--- a/src/core/nm-act-request.h
+++ b/src/core/nm-act-request.h
@@ -38,14 +38,6 @@ NMConnection *nm_act_request_get_applied_connection(NMActRequest *req);
/*****************************************************************************/
-struct _NMUtilsShareRules;
-
-struct _NMUtilsShareRules *nm_act_request_get_shared(NMActRequest *req);
-
-void nm_act_request_set_shared(NMActRequest *req, struct _NMUtilsShareRules *rules);
-
-/*****************************************************************************/
-
/* Secrets handling */
typedef void (*NMActRequestSecretsFunc)(NMActRequest * req,
diff --git a/src/core/nm-dhcp-config.c b/src/core/nm-dhcp-config.c
index c77e0adbaf..96b5312b4a 100644
--- a/src/core/nm-dhcp-config.c
+++ b/src/core/nm-dhcp-config.c
@@ -8,9 +8,11 @@
#include "nm-dhcp-config.h"
#include "nm-dbus-interface.h"
+#include "NetworkManagerUtils.h"
#include "nm-utils.h"
#include "nm-dbus-object.h"
#include "nm-core-utils.h"
+#include "nm-l3-config-data.h"
/*****************************************************************************/
@@ -49,7 +51,8 @@ static GType nm_dhcp6_config_get_type(void);
NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpConfig, PROP_OPTIONS, );
typedef struct {
- GVariant *options;
+ const NML3ConfigData *l3cd;
+ GVariant * options;
} NMDhcpConfigPrivate;
struct _NMDhcpConfig {
@@ -77,17 +80,41 @@ nm_dhcp_config_get_addr_family(NMDhcpConfig *self)
/*****************************************************************************/
void
-nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options)
+nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd)
{
- NMDhcpConfigPrivate *priv;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd2 = NULL;
+ gs_unref_variant GVariant *options2 = NULL;
+ NMDhcpConfigPrivate * priv;
g_return_if_fail(NM_IS_DHCP_CONFIG(self));
- g_return_if_fail(options);
priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
- nm_g_variant_unref(priv->options);
- priv->options = g_variant_ref_sink(nm_utils_strdict_to_variant_asv(options));
+ if (priv->l3cd == l3cd)
+ return;
+
+ if (l3cd)
+ nm_l3_config_data_ref_and_seal(l3cd);
+ NM_SWAP(&priv->l3cd, &l3cd);
+
+ options2 = NULL;
+ if (priv->l3cd) {
+ NMDhcpLease *lease;
+
+ lease = nm_l3_config_data_get_dhcp_lease(priv->l3cd, nm_dhcp_config_get_addr_family(self));
+ if (lease)
+ options2 = nm_utils_strdict_to_variant_asv(nm_dhcp_lease_get_options(lease));
+ }
+ if (!options2)
+ options2 = nm_g_variant_singleton_aLsvI();
+
+ options2 = g_variant_ref_sink(options2);
+
+ if (g_variant_equal(priv->options, options2))
+ return;
+
+ NM_SWAP(&priv->options, &options2);
+
_notify(self, PROP_OPTIONS);
}
@@ -95,19 +122,22 @@ const char *
nm_dhcp_config_get_option(NMDhcpConfig *self, const char *key)
{
NMDhcpConfigPrivate *priv;
- const char * value;
+ NMDhcpLease * lease;
g_return_val_if_fail(NM_IS_DHCP_CONFIG(self), NULL);
g_return_val_if_fail(key, NULL);
priv = NM_DHCP_CONFIG_GET_PRIVATE(self);
- if (priv->options && g_variant_lookup(priv->options, key, "&s", &value))
- return value;
- else
+ if (!priv->l3cd)
return NULL;
+
+ lease = nm_l3_config_data_get_dhcp_lease(priv->l3cd, nm_dhcp_config_get_addr_family(self));
+ return nm_dhcp_lease_lookup_option(lease, key);
}
+/*****************************************************************************/
+
GVariant *
nm_dhcp_config_get_options(NMDhcpConfig *self)
{
@@ -125,7 +155,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
switch (prop_id) {
case PROP_OPTIONS:
- g_value_set_variant(value, priv->options ?: nm_g_variant_singleton_aLsvI());
+ g_value_set_variant(value, priv->options);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -137,7 +167,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
static void
nm_dhcp_config_init(NMDhcpConfig *self)
-{}
+{
+ NM_DHCP_CONFIG_GET_PRIVATE(self)->options = g_variant_ref(nm_g_variant_singleton_aLsvI());
+}
NMDhcpConfig *
nm_dhcp_config_new(int addr_family)
@@ -154,6 +186,8 @@ finalize(GObject *object)
nm_g_variant_unref(priv->options);
+ nm_l3_config_data_unref(priv->l3cd);
+
G_OBJECT_CLASS(nm_dhcp_config_parent_class)->finalize(object);
}
diff --git a/src/core/nm-dhcp-config.h b/src/core/nm-dhcp-config.h
index 9e68f2fb3a..6fb15ebfa9 100644
--- a/src/core/nm-dhcp-config.h
+++ b/src/core/nm-dhcp-config.h
@@ -27,7 +27,7 @@ NMDhcpConfig *nm_dhcp_config_new(int addr_family);
int nm_dhcp_config_get_addr_family(NMDhcpConfig *self);
-void nm_dhcp_config_set_options(NMDhcpConfig *self, GHashTable *options);
+void nm_dhcp_config_set_lease(NMDhcpConfig *self, const NML3ConfigData *l3cd);
const char *nm_dhcp_config_get_option(NMDhcpConfig *self, const char *option);
diff --git a/src/core/nm-dispatcher.c b/src/core/nm-dispatcher.c
index 32c9db627c..efbe50a339 100644
--- a/src/core/nm-dispatcher.c
+++ b/src/core/nm-dispatcher.c
@@ -16,8 +16,7 @@
#include "devices/nm-device.h"
#include "nm-dhcp-config.h"
#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
#include "settings/nm-settings-connection.h"
#include "libnm-platform/nm-platform.h"
@@ -167,31 +166,30 @@ dump_proxy_to_props(NMProxyConfig *proxy, GVariantBuilder *builder)
}
static void
-dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
+dump_ip_to_props(const NML3ConfigData *l3cd, int addr_family, GVariantBuilder *builder)
{
- const int addr_family = nm_ip_config_get_addr_family(ip);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
- const NMPObject *obj;
- GVariantBuilder int_builder;
- NMDedupMultiIter ipconf_iter;
- GVariant * var1;
- GVariant * var2;
- guint n;
- guint i;
- const NMPObject *default_route;
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const NMPObject * obj;
+ GVariantBuilder int_builder;
+ NMDedupMultiIter ipconf_iter;
+ GVariant * var1;
+ GVariant * var2;
+ guint n;
+ guint i;
+ const NMPObject * default_route;
+ const char *const *strarr;
+ const in_addr_t * ip4arr;
+ gconstpointer iparr;
if (IS_IPv4)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuay)"));
- default_route = nm_ip_config_best_default_route_get(ip);
- if (IS_IPv4)
- nm_ip_config_iter_ip4_address_init(&ipconf_iter, NM_IP4_CONFIG(ip));
- else
- nm_ip_config_iter_ip6_address_init(&ipconf_iter, NM_IP6_CONFIG(ip));
- while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
- &obj,
- NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4))) {
+ default_route = nm_l3_config_data_get_best_default_route(l3cd, addr_family);
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
const NMPlatformIPXAddress *addr = NMP_OBJECT_CAST_IPX_ADDRESS(obj);
if (IS_IPv4) {
@@ -225,30 +223,28 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aay"));
- n = nm_ip_config_get_num_nameservers(ip);
+ iparr = nm_l3_config_data_get_nameservers(l3cd, addr_family, &n);
for (i = 0; i < n; i++) {
- if (IS_IPv4) {
- g_variant_builder_add(&int_builder,
- "u",
- nm_ip4_config_get_nameserver(NM_IP4_CONFIG(ip), i));
- } else {
- var1 = nm_g_variant_new_ay_in6addr(nm_ip6_config_get_nameserver(NM_IP6_CONFIG(ip), i));
+ if (IS_IPv4)
+ g_variant_builder_add(&int_builder, "u", ((const in_addr_t *) iparr)[i]);
+ else {
+ var1 = nm_g_variant_new_ay_in6addr(&(((const struct in6_addr *) iparr)[i]));
g_variant_builder_add(&int_builder, "@ay", var1);
}
}
g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder));
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("as"));
- n = nm_ip_config_get_num_domains(ip);
+ strarr = nm_l3_config_data_get_domains(l3cd, addr_family, &n);
for (i = 0; i < n; i++)
- g_variant_builder_add(&int_builder, "s", nm_ip_config_get_domain(ip, i));
+ g_variant_builder_add(&int_builder, "s", strarr[i]);
g_variant_builder_add(builder, "{sv}", "domains", g_variant_builder_end(&int_builder));
if (IS_IPv4) {
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au"));
- n = nm_ip4_config_get_num_wins(NM_IP4_CONFIG(ip));
+ ip4arr = nm_l3_config_data_get_wins(l3cd, &n);
for (i = 0; i < n; i++)
- g_variant_builder_add(&int_builder, "u", nm_ip4_config_get_wins(NM_IP4_CONFIG(ip), i));
+ g_variant_builder_add(&int_builder, "u", ip4arr[i]);
g_variant_builder_add(builder, "{sv}", "wins-servers", g_variant_builder_end(&int_builder));
}
@@ -256,13 +252,10 @@ dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder)
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau"));
else
g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuayu)"));
- if (IS_IPv4)
- nm_ip_config_iter_ip4_route_init(&ipconf_iter, NM_IP4_CONFIG(ip));
- else
- nm_ip_config_iter_ip6_route_init(&ipconf_iter, NM_IP6_CONFIG(ip));
- while (nm_platform_dedup_multi_iter_next_obj(&ipconf_iter,
- &obj,
- NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4))) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
const NMPlatformIPXRoute *route = NMP_OBJECT_CAST_IPX_ROUTE(obj);
if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
@@ -299,10 +292,9 @@ fill_device_props(NMDevice * device,
GVariant ** dhcp4_props,
GVariant ** dhcp6_props)
{
- NMProxyConfig *proxy_config;
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
- NMDhcpConfig * dhcp_config;
+ const NML3ConfigData *l3cd;
+ NMProxyConfig * proxy_config;
+ NMDhcpConfig * dhcp_config;
/* If the action is for a VPN, send the VPN's IP interface instead of the device's */
g_variant_builder_add(dev_builder,
@@ -333,13 +325,11 @@ fill_device_props(NMDevice * device,
if (proxy_config)
dump_proxy_to_props(proxy_config, proxy_builder);
- ip4_config = nm_device_get_ip4_config(device);
- if (ip4_config)
- dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
-
- ip6_config = nm_device_get_ip6_config(device);
- if (ip6_config)
- dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
+ l3cd = nm_device_get_l3cd(device, TRUE);
+ if (l3cd) {
+ dump_ip_to_props(l3cd, AF_INET, ip4_builder);
+ dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
+ }
dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
if (dhcp_config)
@@ -351,19 +341,18 @@ fill_device_props(NMDevice * device,
}
static void
-fill_vpn_props(NMProxyConfig * proxy_config,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config,
- GVariantBuilder *proxy_builder,
- GVariantBuilder *ip4_builder,
- GVariantBuilder *ip6_builder)
+fill_vpn_props(NMProxyConfig * proxy_config,
+ const NML3ConfigData *l3cd,
+ GVariantBuilder * proxy_builder,
+ GVariantBuilder * ip4_builder,
+ GVariantBuilder * ip6_builder)
{
if (proxy_config)
dump_proxy_to_props(proxy_config, proxy_builder);
- if (ip4_config)
- dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder);
- if (ip6_config)
- dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder);
+ if (l3cd) {
+ dump_ip_to_props(l3cd, AF_INET, ip4_builder);
+ dump_ip_to_props(l3cd, AF_INET6, ip6_builder);
+ }
}
static const char *
@@ -480,8 +469,7 @@ _dispatcher_call(NMDispatcherAction action,
NMConnectivityState connectivity_state,
const char * vpn_iface,
NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id)
@@ -593,10 +581,9 @@ _dispatcher_call(NMDispatcherAction action,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props);
- if (vpn_ip4_config || vpn_ip6_config) {
+ if (l3cd) {
fill_vpn_props(vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
&vpn_proxy_props,
&vpn_ip4_props,
&vpn_ip6_props);
@@ -694,7 +681,6 @@ nm_dispatcher_call_hostname(NMDispatcherFunc callback,
NULL,
NULL,
NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -745,7 +731,6 @@ nm_dispatcher_call_device(NMDispatcherAction action,
NULL,
NULL,
NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -791,7 +776,6 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
NULL,
NULL,
NULL,
- NULL,
NULL);
}
@@ -803,8 +787,7 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
- * @vpn_ip4_config: the #NMIP4Config of the VPN connection
- * @vpn_ip6_config: the #NMIP6Config of the VPN connection
+ * @vpn_l3cd: the #NML3ConfigData of the VPN connection
* @callback: a caller-supplied callback to execute when done
* @user_data: caller-supplied pointer passed to @callback
* @out_call_id: on success, a call identifier which can be passed to
@@ -822,8 +805,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
NMDevice * parent_device,
const char * vpn_iface,
NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id)
@@ -837,8 +819,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
callback,
user_data,
out_call_id);
@@ -852,8 +833,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
* @parent_device: the parent #NMDevice of the VPN connection
* @vpn_iface: the IP interface of the VPN tunnel, if any
* @vpn_proxy_config: the #NMProxyConfig of the VPN connection
- * @vpn_ip4_config: the #NMIP4Config of the VPN connection
- * @vpn_ip6_config: the #NMIP6Config of the VPN connection
+ * @vpn_l3cd: the #NML3ConfigData of the VPN connection
*
* This method always invokes the dispatcher action synchronously and it may
* take a long time to return.
@@ -867,8 +847,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMDevice * parent_device,
const char * vpn_iface,
NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config)
+ const NML3ConfigData *l3cd)
{
return _dispatcher_call(action,
TRUE,
@@ -879,8 +858,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
NULL,
NULL,
NULL);
@@ -914,7 +892,6 @@ nm_dispatcher_call_connectivity(NMConnectivityState connectivity_state,
NULL,
NULL,
NULL,
- NULL,
callback,
user_data,
out_call_id);
diff --git a/src/core/nm-dispatcher.h b/src/core/nm-dispatcher.h
index d588de4e8f..783b3ebe66 100644
--- a/src/core/nm-dispatcher.h
+++ b/src/core/nm-dispatcher.h
@@ -49,8 +49,7 @@ gboolean nm_dispatcher_call_vpn(NMDispatcherAction action,
NMDevice * parent_device,
const char * vpn_iface,
NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config,
+ const NML3ConfigData *l3cd,
NMDispatcherFunc callback,
gpointer user_data,
NMDispatcherCallId ** out_call_id);
@@ -61,8 +60,7 @@ gboolean nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMDevice * parent_device,
const char * vpn_iface,
NMProxyConfig * vpn_proxy_config,
- NMIP4Config * vpn_ip4_config,
- NMIP6Config * vpn_ip6_config);
+ const NML3ConfigData *l3cd);
gboolean nm_dispatcher_call_connectivity(NMConnectivityState state,
NMDispatcherFunc callback,
diff --git a/src/core/nm-iface-helper.c b/src/core/nm-iface-helper.c
index 227363deac..9440752828 100644
--- a/src/core/nm-iface-helper.c
+++ b/src/core/nm-iface-helper.c
@@ -19,6 +19,8 @@
#include "libnm-glib-aux/nm-c-list.h"
#include "main-utils.h"
+#include "nm-ip4-config.h"
+#include "nm-ip6-config.h"
#include "NetworkManagerUtils.h"
#include "libnm-platform/nm-linux-platform.h"
#include "libnm-platform/nm-platform-utils.h"
@@ -93,16 +95,18 @@ static struct {
/*****************************************************************************/
static void
-dhcp4_state_changed(NMDhcpClient *client,
- NMDhcpState state,
- NMIP4Config * ip4_config,
- GHashTable * options,
- gpointer user_data)
+dhcp4_state_changed(NMDhcpClient * client,
+ NMDhcpState state,
+ NML3ConfigData *l3cfg,
+ gpointer user_data)
{
static NMIP4Config *last_config = NULL;
NMIP4Config * existing;
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
gs_free_error GError *error = NULL;
+ NMIP4Config * ip4_config = NULL; //XXX
+
+ /* FIXME(l3cfg): fix handling metric_any/table_any for routes. */
g_return_if_fail(!ip4_config || NM_IS_IP4_CONFIG(ip4_config));
@@ -666,9 +670,15 @@ main(int argc, char *argv[])
hwaddr,
bcast_hwaddr,
global_opt.uuid,
+<<<<<<< HEAD
RT_TABLE_MAIN,
global_opt.priority_v4,
NM_DHCP_CLIENT_FLAGS_NONE,
+||||||| parent of a2bf185ef259 (core: use NML3ConfigData (WIP))
+ RT_TABLE_MAIN,
+ global_opt.priority_v4,
+=======
+>>>>>>> a2bf185ef259 (core: use NML3ConfigData (WIP))
!!global_opt.dhcp4_hostname,
global_opt.dhcp4_hostname,
global_opt.dhcp4_fqdn,
diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c
index 2426eb4941..20584d10d8 100644
--- a/src/core/nm-ip-config.c
+++ b/src/core/nm-ip-config.c
@@ -48,8 +48,8 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
switch (prop_id) {
case PROP_L3CFG:
/* construct-only */
- priv->l3cfg = nm_g_object_ref(g_value_get_pointer(value));
- nm_assert(!priv->l3cfg || NM_IS_L3CFG(priv->l3cfg));
+ priv->l3cfg = g_object_ref(g_value_get_pointer(value));
+ nm_assert(NM_IS_L3CFG(priv->l3cfg));
break;
case PROP_IS_VPN:
/* construct-only */
@@ -94,7 +94,7 @@ finalize(GObject *object)
NMIPConfig * self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
- nm_g_object_unref(priv->l3cfg);
+ g_object_unref(priv->l3cfg);
G_OBJECT_CLASS(nm_ip_config_parent_class)->finalize(object);
}
diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h
index 7032a2385e..11e3617ce9 100644
--- a/src/core/nm-ip4-config.h
+++ b/src/core/nm-ip4-config.h
@@ -105,6 +105,8 @@ typedef struct _NMIP4ConfigClass NMIP4ConfigClass;
GType nm_ip4_config_get_type(void);
+NMIP4Config *nm_ip4_config_new_l3cfg(NML3Cfg *l3cfg);
+
NMIP4Config *nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex);
NMIP4Config *nm_ip4_config_clone(const NMIP4Config *self);
diff --git a/src/core/nm-ip6-config.h b/src/core/nm-ip6-config.h
index 4aa0ee4e58..61d217d2f8 100644
--- a/src/core/nm-ip6-config.h
+++ b/src/core/nm-ip6-config.h
@@ -60,6 +60,8 @@ typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
GType nm_ip6_config_get_type(void);
+NMIP6Config *nm_ip6_config_new_l3cfg(NML3Cfg *l3cfg);
+
NMIP6Config *nm_ip6_config_new(struct _NMDedupMultiIndex *multi_idx, int ifindex);
NMIP6Config *nm_ip6_config_new_cloned(const NMIP6Config *src);
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index 216dc8d2dd..33366d5dfd 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -2595,8 +2595,6 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat
if (out_generated)
*out_generated = FALSE;
- nm_device_capture_initial_config(device);
-
if (ifindex) {
int master_ifindex = nm_platform_link_get_master(priv->platform, ifindex);
diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c
index 52d9b34e0c..d16082cb85 100644
--- a/src/core/nm-policy.c
+++ b/src/core/nm-policy.c
@@ -1039,10 +1039,14 @@ get_best_ip_config(NMPolicy * self,
nm_assert(device);
+ /* FIXME(l3cfg) */
+ conf = NULL;
+#if 0
if (addr_family == AF_INET)
conf = nm_device_get_ip4_config(device);
else
conf = nm_device_get_ip6_config(device);
+#endif
NM_SET_OUT(out_device, device);
NM_SET_OUT(out_vpn, NULL);
@@ -1906,9 +1910,7 @@ device_state_changed(NMDevice * device,
NMPolicy * self = _PRIV_TO_SELF(priv);
NMActiveConnection * ac;
NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
- NMSettingConnection * s_con = NULL;
+ NMSettingConnection * s_con = NULL;
switch (nm_device_state_reason_check(reason)) {
case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
@@ -2015,6 +2017,8 @@ device_state_changed(NMDevice * device,
nm_dns_manager_begin_updates(priv->dns_manager, __func__);
+ /* FIXME(l3cfg) */
+#if 0
ip4_config = nm_device_get_ip4_config(device);
if (ip4_config)
_dns_manager_set_ip_config(priv->dns_manager,
@@ -2027,6 +2031,7 @@ device_state_changed(NMDevice * device,
NM_IP_CONFIG_CAST(ip6_config),
NM_DNS_IP_CONFIG_TYPE_DEFAULT,
device);
+#endif
update_routing_and_dns(self, FALSE, device);
diff --git a/src/core/ppp/nm-ppp-manager-call.c b/src/core/ppp/nm-ppp-manager-call.c
index 5e84f59610..8adeb8adbe 100644
--- a/src/core/ppp/nm-ppp-manager-call.c
+++ b/src/core/ppp/nm-ppp-manager-call.c
@@ -94,24 +94,6 @@ again:
return ret;
}
-void
-nm_ppp_manager_set_route_parameters(NMPPPManager *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
-{
- const NMPPPOps *ppp_ops = ppp_ops_get();
-
- g_return_if_fail(ppp_ops);
-
- ppp_ops->set_route_parameters(self,
- ip4_route_table,
- ip4_route_metric,
- ip6_route_table,
- ip6_route_metric);
-}
-
gboolean
nm_ppp_manager_start(NMPPPManager *self,
NMActRequest *req,
diff --git a/src/core/ppp/nm-ppp-manager-call.h b/src/core/ppp/nm-ppp-manager-call.h
index c831cf0d61..87d2f93f55 100644
--- a/src/core/ppp/nm-ppp-manager-call.h
+++ b/src/core/ppp/nm-ppp-manager-call.h
@@ -10,12 +10,6 @@
NMPPPManager *nm_ppp_manager_create(const char *iface, GError **error);
-void nm_ppp_manager_set_route_parameters(NMPPPManager *ppp_manager,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric);
-
gboolean nm_ppp_manager_start(NMPPPManager *self,
NMActRequest *req,
const char * ppp_name,
diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c
index fefc5d613d..25c5217980 100644
--- a/src/core/ppp/nm-ppp-manager.c
+++ b/src/core/ppp/nm-ppp-manager.c
@@ -32,8 +32,7 @@
#include "libnm-platform/nm-platform-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "nm-l3-config-data.h"
#include "nm-dbus-object.h"
#include "nm-pppd-plugin.h"
@@ -62,8 +61,7 @@ GType nm_ppp_manager_get_type(void);
enum {
STATE_CHANGED,
IFINDEX_SET,
- IP4_CONFIG,
- IP6_CONFIG,
+ NEW_CONFIG,
STATS,
LAST_SIGNAL
@@ -91,11 +89,6 @@ typedef struct {
/* Monitoring */
int monitor_fd;
guint monitor_id;
-
- guint32 ip4_route_table;
- guint32 ip4_route_metric;
- guint32 ip6_route_table;
- guint32 ip6_route_metric;
} NMPPPManagerPrivate;
struct _NMPPPManager {
@@ -131,30 +124,19 @@ static void _ppp_manager_stop_cancel(NMPPPManagerStopHandle *handle);
/*****************************************************************************/
static void
-_ppp_manager_set_route_parameters(NMPPPManager *self,
- guint32 ip4_route_table,
- guint32 ip4_route_metric,
- guint32 ip6_route_table,
- guint32 ip6_route_metric)
+_emit_signal_new_config(NMPPPManager * self,
+ int addr_family,
+ const NML3ConfigData * l3cd,
+ const NMUtilsIPv6IfaceId *iid)
{
- NMPPPManagerPrivate *priv;
+ nm_assert(NM_IS_PPP_MANAGER(self));
+ nm_assert_addr_family(addr_family);
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ nm_assert((!!iid) == (addr_family == AF_INET6));
- g_return_if_fail(NM_IS_PPP_MANAGER(self));
+ nm_l3_config_data_seal(l3cd);
- priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- if (priv->ip4_route_table != ip4_route_table || priv->ip4_route_metric != ip4_route_metric
- || priv->ip6_route_table != ip6_route_table || priv->ip6_route_metric != ip6_route_metric) {
- priv->ip4_route_table = ip4_route_table;
- priv->ip4_route_metric = ip4_route_metric;
- priv->ip6_route_table = ip6_route_table;
- priv->ip6_route_metric = ip6_route_metric;
-
- _LOGT("route-parameters: table-v4: %u, metric-v4: %u, table-v6: %u, metric-v6: %u",
- priv->ip4_route_table,
- priv->ip4_route_metric,
- priv->ip6_route_table,
- priv->ip6_route_metric);
- }
+ g_signal_emit(self, signals[NEW_CONFIG], 0, addr_family, l3cd, iid);
}
/*****************************************************************************/
@@ -510,12 +492,12 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
GDBusMethodInvocation * invocation,
GVariant * parameters)
{
- NMPPPManager * self = NM_PPP_MANAGER(obj);
- NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- gs_unref_object NMIP4Config *config = NULL;
- NMPlatformIP4Address address;
- guint32 u32, mtu;
- GVariantIter * iter;
+ NMPPPManager * self = NM_PPP_MANAGER(obj);
+ NMPPPManagerPrivate * priv = NM_PPP_MANAGER_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address;
+ guint32 u32, mtu;
+ GVariantIter * iter;
gs_unref_variant GVariant *config_dict = NULL;
_LOGI("(IPv4 Config Get) reply received.");
@@ -527,37 +509,40 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
if (!set_ip_config_common(self, config_dict, &mtu))
goto out;
- config = nm_ip4_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
- if (mtu)
- nm_ip4_config_set_mtu(config, mtu, NM_IP_CONFIG_SOURCE_PPP);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_PPP);
+ nm_l3_config_data_set_mtu(l3cd, mtu);
- memset(&address, 0, sizeof(address));
- address.plen = 32;
+ address = (NMPlatformIP4Address){
+ .plen = 32,
+ };
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_ADDRESS, "u", &u32))
address.address = u32;
+ if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
+ address.plen = u32;
+
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_GATEWAY, "u", &u32)) {
const NMPlatformIP4Route r = {
.ifindex = priv->ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_PPP,
.gateway = u32,
- .table_coerced = nm_platform_route_table_coerce(priv->ip4_route_table),
- .metric = priv->ip4_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
address.peer_address = u32;
} else
address.peer_address = address.address;
- if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_PREFIX, "u", &u32))
- address.plen = u32;
-
- if (address.address && address.plen && address.plen <= 32) {
+ if (address.address && address.plen > 0 && address.plen <= 32) {
address.addr_source = NM_IP_CONFIG_SOURCE_PPP;
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
} else {
_LOGE("invalid IPv4 address received!");
goto out;
@@ -565,18 +550,17 @@ impl_ppp_manager_set_ip4_config(NMDBusObject * obj,
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_DNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_nameserver(config, u32);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &u32);
g_variant_iter_free(iter);
}
if (g_variant_lookup(config_dict, NM_PPP_IP4_CONFIG_WINS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_wins(config, u32);
+ nm_l3_config_data_add_wins(l3cd, u32);
g_variant_iter_free(iter);
}
- /* Push the IP4 config up to the device */
- g_signal_emit(self, signals[IP4_CONFIG], 0, config);
+ _emit_signal_new_config(self, AF_INET, l3cd, NULL);
out:
g_dbus_method_invocation_return_value(invocation, NULL);
@@ -620,14 +604,14 @@ impl_ppp_manager_set_ip6_config(NMDBusObject * obj,
GDBusMethodInvocation * invocation,
GVariant * parameters)
{
- NMPPPManager * self = NM_PPP_MANAGER(obj);
- NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- gs_unref_object NMIP6Config *config = NULL;
- NMPlatformIP6Address addr;
- struct in6_addr a;
- NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
- gboolean has_peer = FALSE;
- gs_unref_variant GVariant *config_dict = NULL;
+ NMPPPManager * self = NM_PPP_MANAGER(obj);
+ NMPPPManagerPrivate * priv = NM_PPP_MANAGER_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address address;
+ struct in6_addr a;
+ NMUtilsIPv6IfaceId iid = NM_UTILS_IPV6_IFACE_ID_INIT;
+ gboolean has_peer = FALSE;
+ gs_unref_variant GVariant *config_dict = NULL;
_LOGI("(IPv6 Config Get) reply received.");
@@ -638,32 +622,34 @@ impl_ppp_manager_set_ip6_config(NMDBusObject * obj,
if (!set_ip_config_common(self, config_dict, NULL))
goto out;
- config = nm_ip6_config_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
+ l3cd = nm_l3_config_data_new(nm_platform_get_multi_idx(NM_PLATFORM_GET), priv->ifindex);
- memset(&addr, 0, sizeof(addr));
- addr.plen = 64;
+ address = (NMPlatformIP6Address){
+ .plen = 64,
+ };
if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_PEER_IID, &a, NULL)) {
const NMPlatformIP6Route r = {
.ifindex = priv->ifindex,
.rt_source = NM_IP_CONFIG_SOURCE_PPP,
.gateway = a,
- .table_coerced = nm_platform_route_table_coerce(priv->ip6_route_table),
- .metric = priv->ip6_route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip6_config_add_route(config, &r, NULL);
- addr.peer_address = a;
- has_peer = TRUE;
+ nm_l3_config_data_add_route_6(l3cd, &r);
+ address.peer_address = a;
+ has_peer = TRUE;
}
- if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &addr.address, &iid)) {
+ if (iid_value_to_ll6_addr(config_dict, NM_PPP_IP6_CONFIG_OUR_IID, &address.address, &iid)) {
if (!has_peer)
- addr.peer_address = addr.address;
- nm_ip6_config_add_address(config, &addr);
+ address.peer_address = address.address;
+ nm_l3_config_data_add_address_6(l3cd, &address);
- /* Push the IPv6 config and interface identifier up to the device */
- g_signal_emit(self, signals[IP6_CONFIG], 0, &iid, config);
+ _emit_signal_new_config(self, AF_INET6, l3cd, &iid);
} else
_LOGE("invalid IPv6 address received!");
@@ -1290,12 +1276,8 @@ nm_ppp_manager_init(NMPPPManager *self)
{
NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE(self);
- priv->ifindex = -1;
- priv->monitor_fd = -1;
- priv->ip4_route_table = RT_TABLE_MAIN;
- priv->ip4_route_metric = 460;
- priv->ip6_route_table = RT_TABLE_MAIN;
- priv->ip6_route_metric = 460;
+ priv->ifindex = -1;
+ priv->monitor_fd = -1;
}
static NMPPPManager *
@@ -1414,18 +1396,7 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
G_TYPE_INT,
G_TYPE_STRING);
- signals[IP4_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_IP4_CONFIG,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 1,
- G_TYPE_OBJECT);
-
- signals[IP6_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_IP6_CONFIG,
+ signals[NEW_CONFIG] = g_signal_new(NM_PPP_MANAGER_SIGNAL_NEW_CONFIG,
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_FIRST,
0,
@@ -1433,9 +1404,10 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
NULL,
NULL,
G_TYPE_NONE,
- 2,
- G_TYPE_POINTER,
- G_TYPE_OBJECT);
+ 3,
+ G_TYPE_INT, /* addr_family */
+ G_TYPE_POINTER, /* (const NML3ConfigData *) */
+ G_TYPE_POINTER); /* (const NMUtilsIPv6IfaceId *) */
signals[STATS] = g_signal_new(NM_PPP_MANAGER_SIGNAL_STATS,
G_OBJECT_CLASS_TYPE(object_class),
@@ -1451,9 +1423,8 @@ nm_ppp_manager_class_init(NMPPPManagerClass *manager_class)
}
const NMPPPOps ppp_ops = {
- .create = _ppp_manager_new,
- .set_route_parameters = _ppp_manager_set_route_parameters,
- .start = _ppp_manager_start,
- .stop = _ppp_manager_stop,
- .stop_cancel = _ppp_manager_stop_cancel,
+ .create = _ppp_manager_new,
+ .start = _ppp_manager_start,
+ .stop = _ppp_manager_stop,
+ .stop_cancel = _ppp_manager_stop_cancel,
};
diff --git a/src/core/ppp/nm-ppp-manager.h b/src/core/ppp/nm-ppp-manager.h
index c41dda2074..9cf465517c 100644
--- a/src/core/ppp/nm-ppp-manager.h
+++ b/src/core/ppp/nm-ppp-manager.h
@@ -11,8 +11,7 @@
#define NM_PPP_MANAGER_SIGNAL_STATE_CHANGED "state-changed"
#define NM_PPP_MANAGER_SIGNAL_IFINDEX_SET "ifindex-set"
-#define NM_PPP_MANAGER_SIGNAL_IP4_CONFIG "ip4-config"
-#define NM_PPP_MANAGER_SIGNAL_IP6_CONFIG "ip6-config"
+#define NM_PPP_MANAGER_SIGNAL_NEW_CONFIG "new-config"
#define NM_PPP_MANAGER_SIGNAL_STATS "stats"
typedef struct _NMPPPManager NMPPPManager;
diff --git a/src/core/ppp/nm-ppp-plugin-api.h b/src/core/ppp/nm-ppp-plugin-api.h
index 647e1c240e..a867b94920 100644
--- a/src/core/ppp/nm-ppp-plugin-api.h
+++ b/src/core/ppp/nm-ppp-plugin-api.h
@@ -11,12 +11,6 @@
typedef const struct {
NMPPPManager *(*create)(const char *iface);
- void (*set_route_parameters)(NMPPPManager *manager,
- guint32 route_table_v4,
- guint32 route_metric_v4,
- guint32 route_table_v6,
- guint32 route_metric_v6);
-
gboolean (*start)(NMPPPManager *manager,
NMActRequest *req,
const char * ppp_name,
diff --git a/src/core/systemd/meson.build b/src/core/systemd/meson.build
index c0d8a27c07..fb1e812fa4 100644
--- a/src/core/systemd/meson.build
+++ b/src/core/systemd/meson.build
@@ -25,8 +25,6 @@ libnm_systemd_core = static_library(
'src/libsystemd-network/sd-dhcp-lease.c',
'src/libsystemd-network/sd-dhcp6-client.c',
'src/libsystemd-network/sd-dhcp6-lease.c',
- 'src/libsystemd-network/sd-ipv4acd.c',
- 'src/libsystemd-network/sd-ipv4ll.c',
'src/libsystemd-network/sd-lldp.c',
'src/libsystemd/sd-event/event-util.c',
'src/libsystemd/sd-event/sd-event.c',
diff --git a/src/core/systemd/nm-sd.h b/src/core/systemd/nm-sd.h
index 0ea4be2229..ad183c67f3 100644
--- a/src/core/systemd/nm-sd.h
+++ b/src/core/systemd/nm-sd.h
@@ -9,7 +9,6 @@
#include "systemd/src/systemd/sd-dhcp-client.h"
#include "systemd/src/systemd/sd-dhcp6-client.h"
#include "systemd/src/systemd/sd-lldp.h"
-#include "systemd/src/systemd/sd-ipv4ll.h"
/*****************************************************************************/
diff --git a/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c
deleted file mode 100644
index af83f51954..0000000000
--- a/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
- Copyright © 2014 Axis Communications AB. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <netinet/if_ether.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "sd-ipv4acd.h"
-
-#include "alloc-util.h"
-#include "arp-util.h"
-#include "ether-addr-util.h"
-#include "event-util.h"
-#include "fd-util.h"
-#include "in-addr-util.h"
-#include "log-link.h"
-#include "network-common.h"
-#include "random-util.h"
-#include "siphash24.h"
-#include "string-table.h"
-#include "string-util.h"
-#include "time-util.h"
-
-/* Constants from the RFC */
-#define PROBE_WAIT_USEC (1U * USEC_PER_SEC)
-#define PROBE_NUM 3U
-#define PROBE_MIN_USEC (1U * USEC_PER_SEC)
-#define PROBE_MAX_USEC (2U * USEC_PER_SEC)
-#define ANNOUNCE_WAIT_USEC (2U * USEC_PER_SEC)
-#define ANNOUNCE_NUM 2U
-#define ANNOUNCE_INTERVAL_USEC (2U * USEC_PER_SEC)
-#define MAX_CONFLICTS 10U
-#define RATE_LIMIT_INTERVAL_USEC (60U * USEC_PER_SEC)
-#define DEFEND_INTERVAL_USEC (10U * USEC_PER_SEC)
-
-typedef enum IPv4ACDState {
- IPV4ACD_STATE_INIT,
- IPV4ACD_STATE_STARTED,
- IPV4ACD_STATE_WAITING_PROBE,
- IPV4ACD_STATE_PROBING,
- IPV4ACD_STATE_WAITING_ANNOUNCE,
- IPV4ACD_STATE_ANNOUNCING,
- IPV4ACD_STATE_RUNNING,
- _IPV4ACD_STATE_MAX,
- _IPV4ACD_STATE_INVALID = -EINVAL,
-} IPv4ACDState;
-
-struct sd_ipv4acd {
- unsigned n_ref;
-
- IPv4ACDState state;
- int ifindex;
- int fd;
-
- char *ifname;
- unsigned n_iteration;
- unsigned n_conflict;
-
- sd_event_source *receive_message_event_source;
- sd_event_source *timer_event_source;
-
- usec_t defend_window;
- be32_t address;
-
- /* External */
- struct ether_addr mac_addr;
-
- sd_event *event;
- int event_priority;
- sd_ipv4acd_callback_t callback;
- void* userdata;
-};
-
-#define log_ipv4acd_errno(acd, error, fmt, ...) \
- ({ \
- int _e = (error); \
- if (DEBUG_LOGGING) \
- log_interface_full_errno( \
- sd_ipv4acd_get_ifname(acd), \
- LOG_DEBUG, _e, "IPv4ACD: " fmt, \
- ##__VA_ARGS__); \
- -ERRNO_VALUE(_e); \
- })
-#define log_ipv4acd(acd, fmt, ...) \
- log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__)
-
-static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = {
- [IPV4ACD_STATE_INIT] = "init",
- [IPV4ACD_STATE_STARTED] = "started",
- [IPV4ACD_STATE_WAITING_PROBE] = "waiting-probe",
- [IPV4ACD_STATE_PROBING] = "probing",
- [IPV4ACD_STATE_WAITING_ANNOUNCE] = "waiting-announce",
- [IPV4ACD_STATE_ANNOUNCING] = "announcing",
- [IPV4ACD_STATE_RUNNING] = "running",
-};
-
-DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state, IPv4ACDState);
-
-static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) {
- assert(acd);
- assert(st < _IPV4ACD_STATE_MAX);
-
- if (st != acd->state)
- log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st));
-
- if (st == acd->state && !reset_counter)
- acd->n_iteration++;
- else {
- acd->state = st;
- acd->n_iteration = 0;
- }
-}
-
-static void ipv4acd_reset(sd_ipv4acd *acd) {
- assert(acd);
-
- (void) event_source_disable(acd->timer_event_source);
- acd->receive_message_event_source = sd_event_source_unref(acd->receive_message_event_source);
-
- acd->fd = safe_close(acd->fd);
-
- ipv4acd_set_state(acd, IPV4ACD_STATE_INIT, true);
-}
-
-static sd_ipv4acd *ipv4acd_free(sd_ipv4acd *acd) {
- assert(acd);
-
- acd->timer_event_source = sd_event_source_unref(acd->timer_event_source);
-
- ipv4acd_reset(acd);
- sd_ipv4acd_detach_event(acd);
- free(acd->ifname);
- return mfree(acd);
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4acd, sd_ipv4acd, ipv4acd_free);
-
-int sd_ipv4acd_new(sd_ipv4acd **ret) {
- _cleanup_(sd_ipv4acd_unrefp) sd_ipv4acd *acd = NULL;
-
- assert_return(ret, -EINVAL);
-
- acd = new(sd_ipv4acd, 1);
- if (!acd)
- return -ENOMEM;
-
- *acd = (sd_ipv4acd) {
- .n_ref = 1,
- .state = IPV4ACD_STATE_INIT,
- .ifindex = -1,
- .fd = -1,
- };
-
- *ret = TAKE_PTR(acd);
-
- return 0;
-}
-
-static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) {
- assert(acd);
-
- if (!acd->callback)
- return;
-
- acd->callback(acd, event, acd->userdata);
-}
-
-int sd_ipv4acd_stop(sd_ipv4acd *acd) {
- IPv4ACDState old_state;
-
- if (!acd)
- return 0;
-
- old_state = acd->state;
-
- ipv4acd_reset(acd);
-
- if (old_state == IPV4ACD_STATE_INIT)
- return 0;
-
- log_ipv4acd(acd, "STOPPED");
-
- ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_STOP);
-
- return 0;
-}
-
-static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata);
-
-static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) {
- usec_t next_timeout, time_now;
-
- assert(acd);
-
- next_timeout = usec;
-
- if (random_usec > 0)
- next_timeout += (usec_t) random_u64() % random_usec;
-
- assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0);
-
- return event_reset_time(acd->event, &acd->timer_event_source,
- clock_boottime_or_monotonic(),
- time_now + next_timeout, 0,
- ipv4acd_on_timeout, acd,
- acd->event_priority, "ipv4acd-timer", true);
-}
-
-static bool ipv4acd_arp_conflict(sd_ipv4acd *acd, struct ether_arp *arp) {
- assert(acd);
- assert(arp);
-
- /* see the BPF */
- if (memcmp(arp->arp_spa, &acd->address, sizeof(acd->address)) == 0)
- return true;
-
- /* the TPA matched instead of the SPA, this is not a conflict */
- return false;
-}
-
-static int ipv4acd_on_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
- sd_ipv4acd *acd = userdata;
- int r = 0;
-
- assert(acd);
-
- switch (acd->state) {
-
- case IPV4ACD_STATE_STARTED:
- ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_PROBE, true);
-
- if (acd->n_conflict >= MAX_CONFLICTS) {
- char ts[FORMAT_TIMESPAN_MAX];
- log_ipv4acd(acd, "Max conflicts reached, delaying by %s", format_timespan(ts, sizeof(ts), RATE_LIMIT_INTERVAL_USEC, 0));
-
- r = ipv4acd_set_next_wakeup(acd, RATE_LIMIT_INTERVAL_USEC, PROBE_WAIT_USEC);
- if (r < 0)
- goto fail;
- } else {
- r = ipv4acd_set_next_wakeup(acd, 0, PROBE_WAIT_USEC);
- if (r < 0)
- goto fail;
- }
-
- break;
-
- case IPV4ACD_STATE_WAITING_PROBE:
- case IPV4ACD_STATE_PROBING:
- /* Send a probe */
- r = arp_send_probe(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
- if (r < 0) {
- log_ipv4acd_errno(acd, r, "Failed to send ARP probe: %m");
- goto fail;
- } else {
- _cleanup_free_ char *address = NULL;
- union in_addr_union addr = { .in.s_addr = acd->address };
-
- (void) in_addr_to_string(AF_INET, &addr, &address);
- log_ipv4acd(acd, "Probing %s", strna(address));
- }
-
- if (acd->n_iteration < PROBE_NUM - 2) {
- ipv4acd_set_state(acd, IPV4ACD_STATE_PROBING, false);
-
- r = ipv4acd_set_next_wakeup(acd, PROBE_MIN_USEC, (PROBE_MAX_USEC-PROBE_MIN_USEC));
- if (r < 0)
- goto fail;
- } else {
- ipv4acd_set_state(acd, IPV4ACD_STATE_WAITING_ANNOUNCE, true);
-
- r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_WAIT_USEC, 0);
- if (r < 0)
- goto fail;
- }
-
- break;
-
- case IPV4ACD_STATE_ANNOUNCING:
- if (acd->n_iteration >= ANNOUNCE_NUM - 1) {
- ipv4acd_set_state(acd, IPV4ACD_STATE_RUNNING, false);
- break;
- }
-
- _fallthrough_;
- case IPV4ACD_STATE_WAITING_ANNOUNCE:
- /* Send announcement packet */
- r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
- if (r < 0) {
- log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
- goto fail;
- } else
- log_ipv4acd(acd, "ANNOUNCE");
-
- ipv4acd_set_state(acd, IPV4ACD_STATE_ANNOUNCING, false);
-
- r = ipv4acd_set_next_wakeup(acd, ANNOUNCE_INTERVAL_USEC, 0);
- if (r < 0)
- goto fail;
-
- if (acd->n_iteration == 0) {
- acd->n_conflict = 0;
- ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_BIND);
- }
-
- break;
-
- default:
- assert_not_reached("Invalid state.");
- }
-
- return 0;
-
-fail:
- sd_ipv4acd_stop(acd);
- return 0;
-}
-
-static void ipv4acd_on_conflict(sd_ipv4acd *acd) {
- _cleanup_free_ char *address = NULL;
- union in_addr_union addr = { .in.s_addr = acd->address };
-
- assert(acd);
-
- acd->n_conflict++;
-
- (void) in_addr_to_string(AF_INET, &addr, &address);
- log_ipv4acd(acd, "Conflict on %s (%u)", strna(address), acd->n_conflict);
-
- ipv4acd_reset(acd);
- ipv4acd_client_notify(acd, SD_IPV4ACD_EVENT_CONFLICT);
-}
-
-static int ipv4acd_on_packet(
- sd_event_source *s,
- int fd,
- uint32_t revents,
- void *userdata) {
-
- sd_ipv4acd *acd = userdata;
- struct ether_arp packet;
- ssize_t n;
- int r;
-
- assert(s);
- assert(acd);
- assert(fd >= 0);
-
- n = recv(fd, &packet, sizeof(struct ether_arp), 0);
- if (n < 0) {
- if (IN_SET(errno, EAGAIN, EINTR))
- return 0;
-
- log_ipv4acd_errno(acd, errno, "Failed to read ARP packet: %m");
- goto fail;
- }
- if ((size_t) n != sizeof(struct ether_arp)) {
- log_ipv4acd(acd, "Ignoring too short ARP packet.");
- return 0;
- }
-
- switch (acd->state) {
-
- case IPV4ACD_STATE_ANNOUNCING:
- case IPV4ACD_STATE_RUNNING:
-
- if (ipv4acd_arp_conflict(acd, &packet)) {
- usec_t ts;
-
- assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &ts) >= 0);
-
- /* Defend address */
- if (ts > acd->defend_window) {
- acd->defend_window = ts + DEFEND_INTERVAL_USEC;
- r = arp_send_announcement(acd->fd, acd->ifindex, acd->address, &acd->mac_addr);
- if (r < 0) {
- log_ipv4acd_errno(acd, r, "Failed to send ARP announcement: %m");
- goto fail;
- } else
- log_ipv4acd(acd, "DEFEND");
-
- } else
- ipv4acd_on_conflict(acd);
- }
- break;
-
- case IPV4ACD_STATE_WAITING_PROBE:
- case IPV4ACD_STATE_PROBING:
- case IPV4ACD_STATE_WAITING_ANNOUNCE:
- /* BPF ensures this packet indicates a conflict */
- ipv4acd_on_conflict(acd);
- break;
-
- default:
- assert_not_reached("Invalid state.");
- }
-
- return 0;
-
-fail:
- sd_ipv4acd_stop(acd);
- return 0;
-}
-
-int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) {
- assert_return(acd, -EINVAL);
- assert_return(ifindex > 0, -EINVAL);
- assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
-
- acd->ifindex = ifindex;
-
- return 0;
-}
-
-int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) {
- if (!acd)
- return -EINVAL;
-
- return acd->ifindex;
-}
-
-int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *ifname) {
- assert_return(acd, -EINVAL);
- assert_return(ifname, -EINVAL);
-
- if (!ifname_valid_full(ifname, IFNAME_VALID_ALTERNATIVE))
- return -EINVAL;
-
- return free_and_strdup(&acd->ifname, ifname);
-}
-
-const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd) {
- if (!acd)
- return NULL;
-
- return get_ifname(acd->ifindex, &acd->ifname);
-}
-
-int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) {
- assert_return(acd, -EINVAL);
- assert_return(addr, -EINVAL);
- assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
-
- acd->mac_addr = *addr;
-
- return 0;
-}
-
-int sd_ipv4acd_detach_event(sd_ipv4acd *acd) {
- assert_return(acd, -EINVAL);
-
- acd->event = sd_event_unref(acd->event);
-
- return 0;
-}
-
-int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority) {
- int r;
-
- assert_return(acd, -EINVAL);
- assert_return(!acd->event, -EBUSY);
-
- if (event)
- acd->event = sd_event_ref(event);
- else {
- r = sd_event_default(&acd->event);
- if (r < 0)
- return r;
- }
-
- acd->event_priority = priority;
-
- return 0;
-}
-
-int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata) {
- assert_return(acd, -EINVAL);
-
- acd->callback = cb;
- acd->userdata = userdata;
-
- return 0;
-}
-
-int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address) {
- assert_return(acd, -EINVAL);
- assert_return(address, -EINVAL);
- assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
-
- acd->address = address->s_addr;
-
- return 0;
-}
-
-int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address) {
- assert_return(acd, -EINVAL);
- assert_return(address, -EINVAL);
-
- address->s_addr = acd->address;
-
- return 0;
-}
-
-int sd_ipv4acd_is_running(sd_ipv4acd *acd) {
- assert_return(acd, false);
-
- return acd->state != IPV4ACD_STATE_INIT;
-}
-
-int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts) {
- int r;
-
- assert_return(acd, -EINVAL);
- assert_return(acd->event, -EINVAL);
- assert_return(acd->ifindex > 0, -EINVAL);
- assert_return(acd->address != 0, -EINVAL);
- assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL);
- assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);
-
- r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr);
- if (r < 0)
- return r;
-
- CLOSE_AND_REPLACE(acd->fd, r);
- acd->defend_window = 0;
-
- if (reset_conflicts)
- acd->n_conflict = 0;
-
- r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd);
- if (r < 0)
- goto fail;
-
- r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority);
- if (r < 0)
- goto fail;
-
- (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message");
-
- r = ipv4acd_set_next_wakeup(acd, 0, 0);
- if (r < 0)
- goto fail;
-
- ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true);
- return 0;
-
-fail:
- ipv4acd_reset(acd);
- return r;
-}
diff --git a/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c
deleted file mode 100644
index 202700d2cb..0000000000
--- a/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/***
- Copyright © 2014 Axis Communications AB. All rights reserved.
-***/
-
-#include "nm-sd-adapt-core.h"
-
-#include <arpa/inet.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "sd-id128.h"
-#include "sd-ipv4acd.h"
-#include "sd-ipv4ll.h"
-
-#include "alloc-util.h"
-#include "ether-addr-util.h"
-#include "in-addr-util.h"
-#include "log-link.h"
-#include "random-util.h"
-#include "siphash24.h"
-#include "sparse-endian.h"
-#include "string-util.h"
-#include "util.h"
-
-#define IPV4LL_NETWORK UINT32_C(0xA9FE0000)
-#define IPV4LL_NETMASK UINT32_C(0xFFFF0000)
-
-#define IPV4LL_DONT_DESTROY(ll) \
- _cleanup_(sd_ipv4ll_unrefp) _unused_ sd_ipv4ll *_dont_destroy_##ll = sd_ipv4ll_ref(ll)
-
-struct sd_ipv4ll {
- unsigned n_ref;
-
- sd_ipv4acd *acd;
-
- be32_t address; /* the address pushed to ACD */
- struct ether_addr mac;
-
- struct {
- le64_t value;
- le64_t generation;
- } seed;
- bool seed_set;
-
- /* External */
- be32_t claimed_address;
-
- sd_ipv4ll_callback_t callback;
- void* userdata;
-};
-
-#define log_ipv4ll_errno(ll, error, fmt, ...) \
- ({ \
- int _e = (error); \
- if (DEBUG_LOGGING) \
- log_interface_full_errno( \
- sd_ipv4ll_get_ifname(ll), \
- LOG_DEBUG, _e, "IPv4LL: " fmt, \
- ##__VA_ARGS__); \
- -ERRNO_VALUE(_e); \
- })
-#define log_ipv4ll(ll, fmt, ...) \
- log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__)
-
-static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata);
-
-static sd_ipv4ll *ipv4ll_free(sd_ipv4ll *ll) {
- assert(ll);
-
- sd_ipv4acd_unref(ll->acd);
- return mfree(ll);
-}
-
-DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_ipv4ll, sd_ipv4ll, ipv4ll_free);
-
-int sd_ipv4ll_new(sd_ipv4ll **ret) {
- _cleanup_(sd_ipv4ll_unrefp) sd_ipv4ll *ll = NULL;
- int r;
-
- assert_return(ret, -EINVAL);
-
- ll = new0(sd_ipv4ll, 1);
- if (!ll)
- return -ENOMEM;
-
- ll->n_ref = 1;
-
- r = sd_ipv4acd_new(&ll->acd);
- if (r < 0)
- return r;
-
- r = sd_ipv4acd_set_callback(ll->acd, ipv4ll_on_acd, ll);
- if (r < 0)
- return r;
-
- *ret = TAKE_PTR(ll);
-
- return 0;
-}
-
-int sd_ipv4ll_stop(sd_ipv4ll *ll) {
- if (!ll)
- return 0;
-
- return sd_ipv4acd_stop(ll->acd);
-}
-
-int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) {
- assert_return(ll, -EINVAL);
- assert_return(ifindex > 0, -EINVAL);
- assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
-
- return sd_ipv4acd_set_ifindex(ll->acd, ifindex);
-}
-
-int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) {
- if (!ll)
- return -EINVAL;
-
- return sd_ipv4acd_get_ifindex(ll->acd);
-}
-
-int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *ifname) {
- assert_return(ll, -EINVAL);
- assert_return(ifname, -EINVAL);
-
- return sd_ipv4acd_set_ifname(ll->acd, ifname);
-}
-
-const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll) {
- if (!ll)
- return NULL;
-
- return sd_ipv4acd_get_ifname(ll->acd);
-}
-
-int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) {
- int r;
-
- assert_return(ll, -EINVAL);
- assert_return(addr, -EINVAL);
- assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
-
- r = sd_ipv4acd_set_mac(ll->acd, addr);
- if (r < 0)
- return r;
-
- ll->mac = *addr;
- return 0;
-}
-
-int sd_ipv4ll_detach_event(sd_ipv4ll *ll) {
- assert_return(ll, -EINVAL);
-
- return sd_ipv4acd_detach_event(ll->acd);
-}
-
-int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority) {
- assert_return(ll, -EINVAL);
-
- return sd_ipv4acd_attach_event(ll->acd, event, priority);
-}
-
-int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata) {
- assert_return(ll, -EINVAL);
-
- ll->callback = cb;
- ll->userdata = userdata;
-
- return 0;
-}
-
-int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address) {
- assert_return(ll, -EINVAL);
- assert_return(address, -EINVAL);
-
- if (ll->claimed_address == 0)
- return -ENOENT;
-
- address->s_addr = ll->claimed_address;
-
- return 0;
-}
-
-int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed) {
- assert_return(ll, -EINVAL);
- assert_return(sd_ipv4ll_is_running(ll) == 0, -EBUSY);
-
- ll->seed.value = htole64(seed);
- ll->seed_set = true;
-
- return 0;
-}
-
-int sd_ipv4ll_is_running(sd_ipv4ll *ll) {
- assert_return(ll, false);
-
- return sd_ipv4acd_is_running(ll->acd);
-}
-
-static bool ipv4ll_address_is_valid(const struct in_addr *address) {
- assert(address);
-
- if (!in4_addr_is_link_local(address))
- return false;
-
- return !IN_SET(be32toh(address->s_addr) & 0x0000FF00U, 0x0000U, 0xFF00U);
-}
-
-int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
- int r;
-
- assert_return(ll, -EINVAL);
- assert_return(address, -EINVAL);
- assert_return(ipv4ll_address_is_valid(address), -EINVAL);
-
- r = sd_ipv4acd_set_address(ll->acd, address);
- if (r < 0)
- return r;
-
- ll->address = address->s_addr;
-
- return 0;
-}
-
-#define PICK_HASH_KEY SD_ID128_MAKE(15,ac,82,a6,d6,3f,49,78,98,77,5d,0c,69,02,94,0b)
-
-static int ipv4ll_pick_address(sd_ipv4ll *ll) {
- _cleanup_free_ char *address = NULL;
- be32_t addr;
-
- assert(ll);
-
- do {
- uint64_t h;
-
- h = siphash24(&ll->seed, sizeof(ll->seed), PICK_HASH_KEY.bytes);
-
- /* Increase the generation counter by one */
- ll->seed.generation = htole64(le64toh(ll->seed.generation) + 1);
-
- addr = htobe32((h & UINT32_C(0x0000FFFF)) | IPV4LL_NETWORK);
- } while (addr == ll->address ||
- IN_SET(be32toh(addr) & 0x0000FF00U, 0x0000U, 0xFF00U));
-
- (void) in_addr_to_string(AF_INET, &(union in_addr_union) { .in.s_addr = addr }, &address);
- log_ipv4ll(ll, "Picked new IP address %s.", strna(address));
-
- return sd_ipv4ll_set_address(ll, &(struct in_addr) { addr });
-}
-
-#define MAC_HASH_KEY SD_ID128_MAKE(df,04,22,98,3f,ad,14,52,f9,87,2e,d1,9c,70,e2,f2)
-
-static int ipv4ll_start_internal(sd_ipv4ll *ll, bool reset_generation) {
- int r;
- bool picked_address = false;
-
- assert_return(ll, -EINVAL);
- assert_return(!ether_addr_is_null(&ll->mac), -EINVAL);
-
- /* If no random seed is set, generate some from the MAC address */
- if (!ll->seed_set)
- ll->seed.value = htole64(siphash24(ll->mac.ether_addr_octet, ETH_ALEN, MAC_HASH_KEY.bytes));
-
- if (reset_generation)
- ll->seed.generation = 0;
-
- if (ll->address == 0) {
- r = ipv4ll_pick_address(ll);
- if (r < 0)
- return r;
-
- picked_address = true;
- }
-
- r = sd_ipv4acd_start(ll->acd, reset_generation);
- if (r < 0) {
-
- /* We couldn't start? If so, let's forget the picked address again, the user might make a change and
- * retry, and we want the new data to take effect when picking an address. */
- if (picked_address)
- ll->address = 0;
-
- return r;
- }
-
- return 1;
-}
-
-int sd_ipv4ll_start(sd_ipv4ll *ll) {
- assert_return(ll, -EINVAL);
-
- if (sd_ipv4ll_is_running(ll))
- return 0;
-
- return ipv4ll_start_internal(ll, true);
-}
-
-int sd_ipv4ll_restart(sd_ipv4ll *ll) {
- ll->address = 0;
-
- return ipv4ll_start_internal(ll, false);
-}
-
-static void ipv4ll_client_notify(sd_ipv4ll *ll, int event) {
- assert(ll);
-
- if (ll->callback)
- ll->callback(ll, event, ll->userdata);
-}
-
-void ipv4ll_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
- sd_ipv4ll *ll = userdata;
- IPV4LL_DONT_DESTROY(ll);
- int r;
-
- assert(acd);
- assert(ll);
-
- switch (event) {
-
- case SD_IPV4ACD_EVENT_STOP:
- ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP);
- ll->claimed_address = 0;
- break;
-
- case SD_IPV4ACD_EVENT_BIND:
- ll->claimed_address = ll->address;
- ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_BIND);
- break;
-
- case SD_IPV4ACD_EVENT_CONFLICT:
- /* if an address was already bound we must call up to the
- user to handle this, otherwise we just try again */
- if (ll->claimed_address != 0) {
- ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_CONFLICT);
-
- ll->claimed_address = 0;
- } else {
- r = sd_ipv4ll_restart(ll);
- if (r < 0)
- goto error;
- }
-
- break;
-
- default:
- assert_not_reached("Invalid IPv4ACD event.");
- }
-
- return;
-
-error:
- ipv4ll_client_notify(ll, SD_IPV4LL_EVENT_STOP);
-}
diff --git a/src/core/systemd/src/systemd/sd-ipv4acd.h b/src/core/systemd/src/systemd/sd-ipv4acd.h
deleted file mode 100644
index 1e89a81b31..0000000000
--- a/src/core/systemd/src/systemd/sd-ipv4acd.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosdipv4acdfoo
-#define foosdipv4acdfoo
-
-/***
- Copyright © 2014 Axis Communications AB. All rights reserved.
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/ethernet.h>
-#include <netinet/in.h>
-#include <stdbool.h>
-
-#include "sd-event.h"
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-enum {
- SD_IPV4ACD_EVENT_STOP = 0,
- SD_IPV4ACD_EVENT_BIND = 1,
- SD_IPV4ACD_EVENT_CONFLICT = 2,
-};
-
-typedef struct sd_ipv4acd sd_ipv4acd;
-typedef void (*sd_ipv4acd_callback_t)(sd_ipv4acd *acd, int event, void *userdata);
-
-int sd_ipv4acd_detach_event(sd_ipv4acd *acd);
-int sd_ipv4acd_attach_event(sd_ipv4acd *acd, sd_event *event, int64_t priority);
-int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address);
-int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata);
-int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr);
-int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index);
-int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd);
-int sd_ipv4acd_set_ifname(sd_ipv4acd *acd, const char *interface_name);
-const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd);
-int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address);
-int sd_ipv4acd_is_running(sd_ipv4acd *acd);
-int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts);
-int sd_ipv4acd_stop(sd_ipv4acd *acd);
-sd_ipv4acd *sd_ipv4acd_ref(sd_ipv4acd *acd);
-sd_ipv4acd *sd_ipv4acd_unref(sd_ipv4acd *acd);
-int sd_ipv4acd_new(sd_ipv4acd **ret);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4acd, sd_ipv4acd_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif
diff --git a/src/core/systemd/src/systemd/sd-ipv4ll.h b/src/core/systemd/src/systemd/sd-ipv4ll.h
deleted file mode 100644
index bf5596ab61..0000000000
--- a/src/core/systemd/src/systemd/sd-ipv4ll.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-#ifndef foosdipv4llfoo
-#define foosdipv4llfoo
-
-/***
- Copyright © 2014 Axis Communications AB. All rights reserved.
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/ethernet.h>
-#include <netinet/in.h>
-
-#include "sd-event.h"
-
-#include "_sd-common.h"
-
-_SD_BEGIN_DECLARATIONS;
-
-enum {
- SD_IPV4LL_EVENT_STOP = 0,
- SD_IPV4LL_EVENT_BIND = 1,
- SD_IPV4LL_EVENT_CONFLICT = 2,
-};
-
-typedef struct sd_ipv4ll sd_ipv4ll;
-typedef void (*sd_ipv4ll_callback_t)(sd_ipv4ll *ll, int event, void *userdata);
-
-int sd_ipv4ll_detach_event(sd_ipv4ll *ll);
-int sd_ipv4ll_attach_event(sd_ipv4ll *ll, sd_event *event, int64_t priority);
-int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
-int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata);
-int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
-int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index);
-int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll);
-int sd_ipv4ll_set_ifname(sd_ipv4ll *ll, const char *interface_name);
-const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll);
-int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
-int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed);
-int sd_ipv4ll_is_running(sd_ipv4ll *ll);
-int sd_ipv4ll_restart(sd_ipv4ll *ll);
-int sd_ipv4ll_start(sd_ipv4ll *ll);
-int sd_ipv4ll_stop(sd_ipv4ll *ll);
-sd_ipv4ll *sd_ipv4ll_ref(sd_ipv4ll *ll);
-sd_ipv4ll *sd_ipv4ll_unref(sd_ipv4ll *ll);
-int sd_ipv4ll_new(sd_ipv4ll **ret);
-
-_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ipv4ll, sd_ipv4ll_unref);
-
-_SD_END_DECLARATIONS;
-
-#endif
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index 2dbbae9105..5b8bec69f6 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -18,8 +18,6 @@
#include <linux/rtnetlink.h>
#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-active-connection.h"
#include "NetworkManagerUtils.h"
@@ -34,6 +32,7 @@
#include "nm-vpn-plugin-info.h"
#include "nm-vpn-manager.h"
#include "dns/nm-dns-manager.h"
+#include "nm-l3-config-data.h"
typedef enum {
/* Only system secrets */
@@ -100,7 +99,7 @@ typedef struct {
NMNetns *netns;
- GPtrArray *ip4_dev_route_blacklist;
+ NML3Cfg *l3cfg;
GDBusProxy * proxy;
GCancellable * cancellable;
@@ -110,10 +109,18 @@ typedef struct {
NMPacrunnerConfId *pacrunner_conf_id;
gboolean has_ip4;
NMIP4Config * ip4_config;
- guint32 ip4_internal_gw;
- guint32 ip4_external_gw;
- gboolean has_ip6;
- NMIP6Config * ip6_config;
+
+ union {
+ struct {
+ const NML3ConfigData *l3cd_6;
+ const NML3ConfigData *l3cd_4;
+ };
+ const NML3ConfigData *l3cd_x[2];
+ };
+ guint32 ip4_internal_gw;
+ guint32 ip4_external_gw;
+ gboolean has_ip6;
+ NMIP6Config *ip6_config;
/* These config instances are passed on to NMDevice and modified by NMDevice.
* This pointer is only useful for nm_device_replace_vpn4_config() to clear the
@@ -351,6 +358,8 @@ fw_call_cleanup(NMVpnConnection *self)
static void
remove_parent_device_config(NMVpnConnection *connection, NMDevice *device)
{
+ /* FIXME(l3cfg) */
+#if 0
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(connection);
if (priv->last_device_ip4_config) {
@@ -362,6 +371,7 @@ remove_parent_device_config(NMVpnConnection *connection, NMDevice *device)
nm_device_replace_vpn6_config(device, priv->last_device_ip6_config, NULL);
g_clear_object(&priv->last_device_ip6_config);
}
+#endif
}
static void
@@ -515,8 +525,7 @@ _set_vpn_state(NMVpnConnection * self,
parent_dev,
priv->ip_iface,
priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
dispatcher_pre_up_done,
self,
&priv->dispatcher_id)) {
@@ -537,8 +546,7 @@ _set_vpn_state(NMVpnConnection * self,
parent_dev,
priv->ip_iface,
priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
NULL,
NULL,
NULL);
@@ -561,8 +569,8 @@ _set_vpn_state(NMVpnConnection * self,
parent_dev,
priv->ip_iface,
priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config);
+ NULL //XXX
+ );
} else {
if (!nm_dispatcher_call_vpn(NM_DISPATCHER_ACTION_VPN_PRE_DOWN,
_get_settings_connection(self, FALSE),
@@ -570,8 +578,7 @@ _set_vpn_state(NMVpnConnection * self,
parent_dev,
priv->ip_iface,
priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
dispatcher_pre_down_done,
self,
&priv->dispatcher_id)) {
@@ -593,7 +600,6 @@ _set_vpn_state(NMVpnConnection * self,
parent_dev,
priv->ip_iface,
NULL,
- NULL,
NULL);
} else {
nm_dispatcher_call_vpn(NM_DISPATCHER_ACTION_VPN_DOWN,
@@ -605,7 +611,6 @@ _set_vpn_state(NMVpnConnection * self,
NULL,
NULL,
NULL,
- NULL,
NULL);
}
}
@@ -678,11 +683,12 @@ device_state_changed(NMActiveConnection *active,
*/
}
-static void
-add_ip4_vpn_gateway_route(NMIP4Config *config,
- NMDevice * parent_device,
- in_addr_t vpn_gw,
- NMPlatform * platform)
+//XXX
+_nm_unused static void
+add_ip4_vpn_gateway_route(NML3ConfigData *l3cd,
+ NMDevice * parent_device,
+ in_addr_t vpn_gw,
+ NMPlatform * platform)
{
guint32 parent_gw = 0;
gboolean has_parent_gw = FALSE;
@@ -691,11 +697,11 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
guint32 route_metric;
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
- g_return_if_fail(NM_IS_IP4_CONFIG(config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
g_return_if_fail(NM_IS_DEVICE(parent_device));
g_return_if_fail(vpn_gw != 0);
- ifindex = nm_ip4_config_get_ifindex(config);
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
nm_assert(ifindex > 0);
nm_assert(ifindex == nm_device_get_ip_ifindex(parent_device));
@@ -737,14 +743,15 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
route_metric = nm_device_get_route_metric(parent_device, AF_INET);
- memset(&route, 0, sizeof(route));
- route.ifindex = ifindex;
- route.network = vpn_gw;
- route.plen = 32;
- route.gateway = parent_gw;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip4_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP4Route){
+ .ifindex = ifindex,
+ .network = vpn_gw,
+ .plen = 32,
+ .gateway = parent_gw,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_4(l3cd, &route);
if (parent_gw) {
/* Ensure there's a route to the parent device's gateway through the
@@ -752,17 +759,19 @@ add_ip4_vpn_gateway_route(NMIP4Config *config,
* routes include a subnet that matches the parent device's subnet,
* the parent device's gateway would get routed through the VPN and fail.
*/
- memset(&route, 0, sizeof(route));
- route.network = parent_gw;
- route.plen = 32;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip4_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP4Route){
+ .network = parent_gw,
+ .plen = 32,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_4(l3cd, &route);
}
}
-static void
-add_ip6_vpn_gateway_route(NMIP6Config * config,
+//XXX
+_nm_unused static void
+add_ip6_vpn_gateway_route(NML3ConfigData * l3cd,
NMDevice * parent_device,
const struct in6_addr *vpn_gw,
NMPlatform * platform)
@@ -774,11 +783,11 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
guint32 route_metric;
nm_auto_nmpobj const NMPObject *route_resolved = NULL;
- g_return_if_fail(NM_IS_IP6_CONFIG(config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
g_return_if_fail(NM_IS_DEVICE(parent_device));
g_return_if_fail(vpn_gw != NULL);
- ifindex = nm_ip6_config_get_ifindex(config);
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
nm_assert(ifindex > 0);
nm_assert(ifindex == nm_device_get_ip_ifindex(parent_device));
@@ -820,15 +829,15 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
route_metric = nm_device_get_route_metric(parent_device, AF_INET6);
- memset(&route, 0, sizeof(route));
- route.ifindex = ifindex;
- route.network = *vpn_gw;
- route.plen = 128;
- if (parent_gw)
- route.gateway = *parent_gw;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip6_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP6Route){
+ .ifindex = ifindex,
+ .network = *vpn_gw,
+ .plen = 128,
+ .gateway = (parent_gw ? *parent_gw : in6addr_any),
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_6(l3cd, &route);
/* Ensure there's a route to the parent device's gateway through the
* parent device, since if the VPN claims the default route and the VPN
@@ -836,12 +845,13 @@ add_ip6_vpn_gateway_route(NMIP6Config * config,
* the parent device's gateway would get routed through the VPN and fail.
*/
if (parent_gw && !IN6_IS_ADDR_UNSPECIFIED(parent_gw)) {
- memset(&route, 0, sizeof(route));
- route.network = *parent_gw;
- route.plen = 128;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
- route.metric = route_metric;
- nm_ip6_config_add_route(config, &route, NULL);
+ route = (NMPlatformIP6Route){
+ .network = *parent_gw,
+ .plen = 128,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ .metric = route_metric,
+ };
+ nm_l3_config_data_add_route_6(l3cd, &route);
}
}
@@ -988,14 +998,13 @@ plugin_state_changed(NMVpnConnection *self, NMVpnServiceState new_service_state)
static void
print_vpn_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate * priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- const NMPlatformIP4Address *address4;
- const NMPlatformIP6Address *address6;
- char * dns_domain = NULL;
- guint32 num, i;
- char b1[NM_UTILS_INET_ADDRSTRLEN];
- char b2[NM_UTILS_INET_ADDRSTRLEN];
- NMDedupMultiIter ipconf_iter;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ const char *const * strv;
+ guint num;
+ guint i;
+ char b1[NM_UTILS_INET_ADDRSTRLEN];
+ char sbuf1[sizeof(_nm_utils_to_string_buffer)];
+ NMDedupMultiIter ipconf_iter;
if (priv->ip4_external_gw) {
_LOGI("Data: VPN Gateway: %s", _nm_utils_inet4_ntop(priv->ip4_external_gw, b1));
@@ -1005,78 +1014,57 @@ print_vpn_config(NMVpnConnection *self)
_LOGI("Data: Tunnel Device: %s%s%s", NM_PRINT_FMT_QUOTE_STRING(priv->ip_iface));
- if (priv->ip4_config) {
- const NMPlatformIP4Route *route;
-
- _LOGI("Data: IPv4 configuration:");
+ for (i = 0; i < 2; i++) {
+ const gboolean IS_IPv4 = (i == 0);
+ const int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
+ const NML3ConfigData *l3cd = priv->l3cd_x[IS_IPv4];
+ const NMPObject * plobj;
+ const guint8 * p_addrs;
- address4 = nm_ip4_config_get_first_address(priv->ip4_config);
- nm_assert(address4);
+ if (!l3cd) {
+ _LOGI("Data: No IPv%c configuration", nm_utils_addr_family_to_char(addr_family));
+ continue;
+ }
- if (priv->ip4_internal_gw)
- _LOGI("Data: Internal Gateway: %s", _nm_utils_inet4_ntop(priv->ip4_internal_gw, b1));
- _LOGI("Data: Internal Address: %s",
- address4 ? _nm_utils_inet4_ntop(address4->address, b1) : "??");
- _LOGI("Data: Internal Prefix: %d", address4 ? (int) address4->plen : -1);
- _LOGI("Data: Internal Point-to-Point Address: %s",
- _nm_utils_inet4_ntop(address4->peer_address, b1));
+ _LOGI("Data: IPv%c configuration:", nm_utils_addr_family_to_char(addr_family));
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->ip4_config, &route) {
- _LOGI("Data: Static Route: %s/%d Next Hop: %s",
- _nm_utils_inet4_ntop(route->network, b1),
- route->plen,
- _nm_utils_inet4_ntop(route->gateway, b2));
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &plobj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
+ _LOGI("Data: Internal Address: %s",
+ nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof(sbuf1)));
}
- num = nm_ip4_config_get_num_nameservers(priv->ip4_config);
- for (i = 0; i < num; i++) {
- _LOGI("Data: Internal DNS: %s",
- _nm_utils_inet4_ntop(nm_ip4_config_get_nameserver(priv->ip4_config, i), b1));
+ if (IS_IPv4) {
+ if (priv->ip4_internal_gw)
+ _LOGI("Data: Internal Gateway: %s",
+ _nm_utils_inet4_ntop(priv->ip4_internal_gw, b1));
+ } else {
+ if (priv->ip6_internal_gw)
+ _LOGI("Data: Internal Gateway: %s",
+ _nm_utils_inet6_ntop(priv->ip6_internal_gw, b1));
}
- if (nm_ip4_config_get_num_domains(priv->ip4_config) > 0)
- dns_domain = (char *) nm_ip4_config_get_domain(priv->ip4_config, 0);
-
- _LOGI("Data: DNS Domain: '%s'", dns_domain ?: "(none)");
- } else
- _LOGI("Data: No IPv4 configuration");
-
- if (priv->ip6_config) {
- const NMPlatformIP6Route *route;
-
- _LOGI("Data: IPv6 configuration:");
-
- address6 = nm_ip6_config_get_first_address(priv->ip6_config);
- nm_assert(address6);
-
- if (priv->ip6_internal_gw)
- _LOGI("Data: Internal Gateway: %s", _nm_utils_inet6_ntop(priv->ip6_internal_gw, b1));
- _LOGI("Data: Internal Address: %s", _nm_utils_inet6_ntop(&address6->address, b1));
- _LOGI("Data: Internal Prefix: %d", address6->plen);
- _LOGI("Data: Internal Point-to-Point Address: %s",
- _nm_utils_inet6_ntop(&address6->peer_address, b1));
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route) {
- _LOGI("Data: Static Route: %s/%d Next Hop: %s",
- _nm_utils_inet6_ntop(&route->network, b1),
- route->plen,
- _nm_utils_inet6_ntop(&route->gateway, b2));
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &plobj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
+ _LOGI("Data: Static Route: %s",
+ nmp_object_to_string(plobj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf1, sizeof(sbuf1)));
}
- num = nm_ip6_config_get_num_nameservers(priv->ip6_config);
- for (i = 0; i < num; i++) {
- _LOGI("Data: Internal DNS: %s",
- _nm_utils_inet6_ntop(nm_ip6_config_get_nameserver(priv->ip6_config, i), b1));
+ p_addrs = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num);
+ for (i = 0; i < num; i++, p_addrs += nm_utils_addr_family_to_size(addr_family)) {
+ _LOGI("Data: Internal DNS: %s", nm_utils_inet_ntop(addr_family, p_addrs, b1));
}
- if (nm_ip6_config_get_num_domains(priv->ip6_config) > 0)
- dns_domain = (char *) nm_ip6_config_get_domain(priv->ip6_config, 0);
-
- _LOGI("Data: DNS Domain: '%s'", dns_domain ?: "(none)");
- } else
- _LOGI("Data: No IPv6 configuration");
+ strv = nm_l3_config_data_get_domains(l3cd, addr_family, &num);
+ for (i = 0; i < num; i++)
+ _LOGI("Data: DNS Domain: '%s'", strv[i]);
+ }
- if (priv->banner && strlen(priv->banner)) {
+ if (!nm_str_is_empty(priv->banner)) {
_LOGI("Data: Login Banner:");
_LOGI("Data: -----------------------------------------");
_LOGI("Data: %s", priv->banner);
@@ -1087,62 +1075,63 @@ print_vpn_config(NMVpnConnection *self)
static void
apply_parent_device_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMDevice * parent_dev = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(self));
- int ifindex;
- NMIP4Config *vpn4_parent_config = NULL;
- NMIP6Config *vpn6_parent_config = NULL;
+#if 0
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self);
+ NMDevice *parent_dev = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (self));
+ int ifindex;
+ NMIP4Config *vpn4_parent_config = NULL;
+ NMIP6Config *vpn6_parent_config = NULL;
- ifindex = nm_device_get_ip_ifindex(parent_dev);
- if (ifindex > 0) {
- /* If the VPN didn't return a network interface, it is a route-based
+ ifindex = nm_device_get_ip_ifindex (parent_dev);
+ if (ifindex > 0) {
+ /* If the VPN didn't return a network interface, it is a route-based
* VPN (like kernel IPSec) and all IP addressing and routing should
* be done on the parent interface instead.
*/
- if (priv->ip4_config) {
- vpn4_parent_config = nm_ip4_config_new(nm_netns_get_multi_idx(priv->netns), ifindex);
- if (priv->ip_ifindex <= 0)
- nm_ip4_config_merge(vpn4_parent_config,
- priv->ip4_config,
- NM_IP_CONFIG_MERGE_NO_DNS,
- 0);
- }
- if (priv->ip6_config) {
- vpn6_parent_config = nm_ip6_config_new(nm_netns_get_multi_idx(priv->netns), ifindex);
- if (priv->ip_ifindex <= 0)
- nm_ip6_config_merge(vpn6_parent_config,
- priv->ip6_config,
- NM_IP_CONFIG_MERGE_NO_DNS,
- 0);
- }
- }
-
- /* Add any explicit route to the VPN gateway through the parent device */
- if (vpn4_parent_config && priv->ip4_external_gw) {
- add_ip4_vpn_gateway_route(vpn4_parent_config,
- parent_dev,
- priv->ip4_external_gw,
- nm_netns_get_platform(priv->netns));
- }
- if (vpn6_parent_config && priv->ip6_external_gw) {
- add_ip6_vpn_gateway_route(vpn6_parent_config,
- parent_dev,
- priv->ip6_external_gw,
- nm_netns_get_platform(priv->netns));
- }
-
- nm_device_replace_vpn4_config(parent_dev, priv->last_device_ip4_config, vpn4_parent_config);
- g_clear_object(&priv->last_device_ip4_config);
- priv->last_device_ip4_config = vpn4_parent_config;
-
- nm_device_replace_vpn6_config(parent_dev, priv->last_device_ip6_config, vpn6_parent_config);
- g_clear_object(&priv->last_device_ip6_config);
- priv->last_device_ip6_config = vpn6_parent_config;
+ if (priv->ip4_config) {
+ vpn4_parent_config = nm_ip4_config_new (nm_netns_get_multi_idx (priv->netns),
+ ifindex);
+ if (priv->ip_ifindex <= 0)
+ nm_ip4_config_merge (vpn4_parent_config, priv->ip4_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
+ }
+ if (priv->ip6_config) {
+ vpn6_parent_config = nm_ip6_config_new (nm_netns_get_multi_idx (priv->netns),
+ ifindex);
+ if (priv->ip_ifindex <= 0)
+ nm_ip6_config_merge (vpn6_parent_config, priv->ip6_config, NM_IP_CONFIG_MERGE_NO_DNS, 0);
+ }
+ }
+
+ /* Add any explicit route to the VPN gateway through the parent device */
+ if ( vpn4_parent_config
+ && priv->ip4_external_gw) {
+ add_ip4_vpn_gateway_route (vpn4_parent_config,
+ parent_dev,
+ priv->ip4_external_gw,
+ nm_netns_get_platform (priv->netns));
+ }
+ if ( vpn6_parent_config
+ && priv->ip6_external_gw) {
+ add_ip6_vpn_gateway_route (vpn6_parent_config,
+ parent_dev,
+ priv->ip6_external_gw,
+ nm_netns_get_platform (priv->netns));
+ }
+
+ nm_device_replace_vpn4_config (parent_dev, priv->last_device_ip4_config, vpn4_parent_config);
+ g_clear_object (&priv->last_device_ip4_config);
+ priv->last_device_ip4_config = vpn4_parent_config;
+
+ nm_device_replace_vpn6_config (parent_dev, priv->last_device_ip6_config, vpn6_parent_config);
+ g_clear_object (&priv->last_device_ip6_config);
+ priv->last_device_ip6_config = vpn6_parent_config;
+#endif
}
static gboolean
nm_vpn_connection_apply_config(NMVpnConnection *self)
{
+#if 0
NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
apply_parent_device_config(self);
@@ -1189,6 +1178,7 @@ nm_vpn_connection_apply_config(NMVpnConnection *self)
_LOGI("VPN connection: (IP Config Get) complete");
if (priv->vpn_state < STATE_PRE_UP)
_set_vpn_state(self, STATE_PRE_UP, NM_ACTIVE_CONNECTION_STATE_REASON_NONE, FALSE);
+#endif
return TRUE;
}
@@ -1286,26 +1276,23 @@ ip6_addr_from_variant(GVariant *v, struct in6_addr *addr)
g_return_val_if_fail(v, FALSE);
g_return_val_if_fail(addr, FALSE);
+ nm_assert(g_variant_is_of_type(v, G_VARIANT_TYPE("ay")));
- if (g_variant_is_of_type(v, G_VARIANT_TYPE("ay"))) {
- bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8));
- if (len == sizeof(struct in6_addr) && !IN6_IS_ADDR_UNSPECIFIED(bytes)) {
- memcpy(addr, bytes, len);
- return TRUE;
- }
+ bytes = g_variant_get_fixed_array(v, &len, sizeof(guint8));
+ if (len == sizeof(struct in6_addr) && !IN6_IS_ADDR_UNSPECIFIED(bytes)) {
+ memcpy(addr, bytes, len);
+ return TRUE;
}
return FALSE;
}
static struct in6_addr *
-ip6_addr_dup_from_variant(GVariant *v)
+ip6_addr_from_variant_dup(GVariant *v)
{
- struct in6_addr *addr;
+ struct in6_addr addr;
- addr = g_malloc0(sizeof(*addr));
- if (ip6_addr_from_variant(v, addr))
- return addr;
- g_free(addr);
+ if (ip6_addr_from_variant(v, &addr))
+ return nm_memdup(&addr, sizeof(addr));
return NULL;
}
@@ -1377,7 +1364,7 @@ process_generic_config(NMVpnConnection *self, GVariant *dict)
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "u", &u32)) {
priv->ip4_external_gw = u32;
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY, "@ay", &v)) {
- priv->ip6_external_gw = ip6_addr_dup_from_variant(v);
+ priv->ip6_external_gw = ip6_addr_from_variant_dup(v);
g_variant_unref(v);
if (!priv->ip6_external_gw) {
@@ -1486,20 +1473,20 @@ _is_device_vrf(NMVpnConnection *self)
static void
nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMPlatformIP4Address address;
- guint32 u32, route_metric;
- NMSettingIPConfig * s_ip;
- NMSettingConnection * s_con;
- guint32 route_table;
- NMIP4Config * config;
- GVariantIter * iter;
- const char * str;
- GVariant * v;
- gboolean b;
- int ip_ifindex;
- guint32 mss = 0;
- gboolean never_default = FALSE;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address;
+ guint32 u32, route_metric;
+ NMSettingIPConfig * s_ip;
+ NMSettingConnection * s_con;
+ guint32 route_table;
+ GVariantIter * iter;
+ const char * str;
+ GVariant * v;
+ gboolean b;
+ int ip_ifindex;
+ guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail(dict && g_variant_is_of_type(dict, G_VARIANT_TYPE_VARDICT));
@@ -1536,11 +1523,13 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (ip_ifindex <= 0)
g_return_if_reached();
- config = nm_ip4_config_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
- nm_ip4_config_set_dns_priority(config, NM_DNS_PRIORITY_DEFAULT_VPN);
+ l3cd = nm_l3_config_data_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_VPN);
+ nm_l3_config_data_set_dns_priority(l3cd, AF_INET, NM_DNS_PRIORITY_DEFAULT_VPN);
- memset(&address, 0, sizeof(address));
- address.plen = 24;
+ address = (NMPlatformIP4Address){
+ .plen = 24,
+ };
/* Internal address of the VPN subnet's gateway */
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY, "u", &u32))
@@ -1559,23 +1548,22 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (address.address && address.plen && address.plen <= 32) {
address.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip4_config_add_address(config, &address);
+ nm_l3_config_data_add_address_4(l3cd, &address);
} else {
_LOGW("invalid IP4 config received!");
- g_object_unref(config);
nm_vpn_connection_config_maybe_complete(self, FALSE);
return;
}
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_nameserver(config, u32);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &u32);
g_variant_iter_free(iter);
}
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_NBNS, "au", &iter)) {
while (g_variant_iter_next(iter, "u", &u32))
- nm_ip4_config_add_wins(config, u32);
+ nm_l3_config_data_add_wins(l3cd, u32);
g_variant_iter_free(iter);
}
@@ -1583,11 +1571,11 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
mss = u32;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN, "&s", &str))
- nm_ip4_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS, "as", &iter)) {
while (g_variant_iter_next(iter, "&s", &str))
- nm_ip4_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
g_variant_iter_free(iter);
}
@@ -1599,12 +1587,12 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
if (nm_setting_ip_config_get_ignore_auto_routes(s_ip)) {
/* ignore VPN routes */
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_PRESERVE_ROUTES, "b", &b) && b) {
- if (priv->ip4_config) {
- NMDedupMultiIter ipconf_iter;
+ if (priv->l3cd_4) {
const NMPlatformIP4Route *route;
+ NMDedupMultiIter ipconf_iter;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->ip4_config, &route)
- nm_ip4_config_add_route(config, route, NULL);
+ nm_l3_config_data_iter_ip4_route_for_each (&ipconf_iter, priv->l3cd_4, &route)
+ nm_l3_config_data_add_route_4(l3cd, route);
}
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES, "aau", &iter)) {
while (g_variant_iter_next(iter, "@au", &v)) {
@@ -1641,7 +1629,7 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
break;
}
- nm_ip4_config_add_route(config, &route, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
break;
default:
break;
@@ -1655,12 +1643,14 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
never_default = b;
/* Merge in user overrides from the NMConnection's IPv4 setting */
- nm_ip4_config_merge_setting(config,
- s_ip,
- nm_setting_connection_get_mdns(s_con),
- nm_setting_connection_get_llmnr(s_con),
- route_table,
- route_metric);
+ (void) s_con;
+ //XXX
+ //nm_ip4_config_merge_setting (config,
+ // s_ip,
+ // nm_setting_connection_get_mdns (s_con),
+ // nm_setting_connection_get_llmnr (s_con),
+ // route_table,
+ // route_metric);
if (!never_default && !nm_setting_ip_config_get_never_default(s_ip)) {
const NMPlatformIP4Route r = {
@@ -1672,45 +1662,47 @@ nm_vpn_connection_ip4_config_get(NMVpnConnection *self, GVariant *dict)
.mss = mss,
};
- nm_ip4_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
}
- nm_clear_pointer(&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
+ nm_l3_config_data_add_dependent_routes(l3cd,
+ AF_INET,
+ route_table,
+ nm_vpn_connection_get_ip4_route_metric(self),
+ _is_device_vrf(self));
- nm_ip4_config_add_dependent_routes(config,
- route_table,
- nm_vpn_connection_get_ip4_route_metric(self),
- _is_device_vrf(self),
- &priv->ip4_dev_route_blacklist);
+ //XXX
+#if 0
+ if (priv->ip4_config) {
+ nm_ip4_config_replace (priv->ip4_config, config, NULL);
+ g_object_unref (config);
+ } else {
+ priv->ip4_config = config;
+ nm_dbus_object_export (NM_DBUS_OBJECT (config));
+ g_object_notify ((GObject *) self, NM_ACTIVE_CONNECTION_IP4_CONFIG);
+ }
- if (priv->ip4_config) {
- nm_ip4_config_replace(priv->ip4_config, config, NULL);
- g_object_unref(config);
- } else {
- priv->ip4_config = config;
- nm_dbus_object_export(NM_DBUS_OBJECT(config));
- g_object_notify((GObject *) self, NM_ACTIVE_CONNECTION_IP4_CONFIG);
- }
-
- nm_vpn_connection_config_maybe_complete(self, TRUE);
+ nm_vpn_connection_config_maybe_complete (self, TRUE);
+#endif
}
static void
nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
- NMPlatformIP6Address address;
- guint32 u32, route_metric;
- NMSettingIPConfig * s_ip;
- guint32 route_table;
- NMIP6Config * config;
- GVariantIter * iter;
- const char * str;
- GVariant * v;
- gboolean b;
- int ip_ifindex;
- guint32 mss = 0;
- gboolean never_default = FALSE;
+ NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address address;
+ guint32 u32;
+ guint32 route_metric;
+ NMSettingIPConfig * s_ip;
+ guint32 route_table;
+ GVariantIter * iter;
+ const char * str;
+ GVariant * v;
+ gboolean b;
+ int ip_ifindex;
+ guint32 mss = 0;
+ gboolean never_default = FALSE;
g_return_if_fail(dict && g_variant_is_of_type(dict, G_VARIANT_TYPE_VARDICT));
@@ -1734,16 +1726,18 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (ip_ifindex <= 0)
g_return_if_reached();
- config = nm_ip6_config_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
- nm_ip6_config_set_dns_priority(config, NM_DNS_PRIORITY_DEFAULT_VPN);
+ l3cd = nm_l3_config_data_new(nm_netns_get_multi_idx(priv->netns), ip_ifindex);
+ nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_VPN);
+ nm_l3_config_data_set_dns_priority(l3cd, AF_INET6, NM_DNS_PRIORITY_DEFAULT_VPN);
- memset(&address, 0, sizeof(address));
- address.plen = 128;
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ };
/* Internal address of the VPN subnet's gateway */
nm_clear_g_free(&priv->ip6_internal_gw);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY, "@ay", &v)) {
- priv->ip6_internal_gw = ip6_addr_dup_from_variant(v);
+ priv->ip6_internal_gw = ip6_addr_from_variant_dup(v);
g_variant_unref(v);
}
@@ -1762,10 +1756,9 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (!IN6_IS_ADDR_UNSPECIFIED(&address.address) && address.plen && address.plen <= 128) {
address.addr_source = NM_IP_CONFIG_SOURCE_VPN;
- nm_ip6_config_add_address(config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
} else {
_LOGW("invalid IP6 config received!");
- g_object_unref(config);
nm_vpn_connection_config_maybe_complete(self, FALSE);
return;
}
@@ -1775,7 +1768,7 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
struct in6_addr dns;
if (ip6_addr_from_variant(v, &dns))
- nm_ip6_config_add_nameserver(config, &dns);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns);
g_variant_unref(v);
}
g_variant_iter_free(iter);
@@ -1785,11 +1778,11 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
mss = u32;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN, "&s", &str))
- nm_ip6_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET6, str);
if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS, "as", &iter)) {
while (g_variant_iter_next(iter, "&s", &str))
- nm_ip6_config_add_domain(config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET6, str);
g_variant_iter_free(iter);
}
@@ -1800,33 +1793,41 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
if (nm_setting_ip_config_get_ignore_auto_routes(s_ip)) {
/* Ignore VPN routes */
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_PRESERVE_ROUTES, "b", &b) && b) {
- if (priv->ip6_config) {
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Route *route;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->ip6_config, &route)
- nm_ip6_config_add_route(config, route, NULL);
+ if (priv->l3cd_6) {
+ NMDedupMultiIter ipconf_iter;
+ const NMPObject *route;
+
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ priv->l3cd_6,
+ &route,
+ NMP_OBJECT_TYPE_IP6_ROUTE)
+ nm_l3_config_data_add_route(l3cd, AF_INET6, route, NULL);
}
} else if (g_variant_lookup(dict, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES, "a(ayuayu)", &iter)) {
- GVariant *dest, *next_hop;
- guint32 prefix, metric;
+ GVariant *next_hop;
+ GVariant *dest;
+ guint32 prefix;
+ guint32 metric;
while (g_variant_iter_next(iter, "(@ayu@ayu)", &dest, &prefix, &next_hop, &metric)) {
- NMPlatformIP6Route route;
+ _nm_unused gs_unref_variant GVariant *nexT_hop_keep_alive = next_hop;
+ _nm_unused gs_unref_variant GVariant *dest_keep_alive = dest;
+ NMPlatformIP6Route route;
+
+ if (prefix > 128)
+ continue;
- memset(&route, 0, sizeof(route));
+ route = (NMPlatformIP6Route){
+ .plen = prefix,
+ .table_coerced = nm_platform_route_table_coerce(route_table),
+ .metric = route_metric,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ };
if (!ip6_addr_from_variant(dest, &route.network))
- goto next;
-
- if (prefix > 128)
- goto next;
+ continue;
- route.plen = prefix;
ip6_addr_from_variant(next_hop, &route.gateway);
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- route.metric = route_metric;
- route.rt_source = NM_IP_CONFIG_SOURCE_VPN;
nm_utils_ip6_address_clear_host_address(&route.network, &route.network, route.plen);
@@ -1837,14 +1838,10 @@ nm_vpn_connection_ip6_config_get(NMVpnConnection *self, GVariant *dict)
* server, we want to use the NM created route instead of whatever
* the server provides.
*/
- goto next;
+ continue;
}
- nm_ip6_config_add_route(config, &route, NULL);
-
-next:
- g_variant_unref(dest);
- g_variant_unref(next_hop);
+ nm_l3_config_data_add_route_6(l3cd, &route);
}
g_variant_iter_free(iter);
}
@@ -1853,7 +1850,12 @@ next:
never_default = b;
/* Merge in user overrides from the NMConnection's IPv6 setting */
- nm_ip6_config_merge_setting(config, s_ip, route_table, route_metric);
+ //XXX
+ (void) s_ip;
+ //nm_ip6_config_merge_setting (config,
+ // s_ip,
+ // route_table,
+ // route_metric);
if (!never_default && !nm_setting_ip_config_get_never_default(s_ip)) {
const NMPlatformIP6Route r = {
@@ -1865,19 +1867,26 @@ next:
.mss = mss,
};
- nm_ip6_config_add_route(config, &r, NULL);
+ nm_l3_config_data_add_route_6(l3cd, &r);
}
- nm_ip6_config_add_dependent_routes(config, route_table, route_metric, _is_device_vrf(self));
+ nm_l3_config_data_add_dependent_routes(l3cd,
+ AF_INET6,
+ route_table,
+ route_metric,
+ _is_device_vrf(self));
- if (priv->ip6_config) {
- nm_ip6_config_replace(priv->ip6_config, config, NULL);
- g_object_unref(config);
- } else {
- priv->ip6_config = config;
- nm_dbus_object_export(NM_DBUS_OBJECT(config));
- g_object_notify((GObject *) self, NM_ACTIVE_CONNECTION_IP6_CONFIG);
- }
+ //XXX
+#if 0
+ if (priv->ip6_config) {
+ nm_ip6_config_replace (priv->ip6_config, config, NULL);
+ g_object_unref (config);
+ } else {
+ priv->ip6_config = config;
+ nm_dbus_object_export (NM_DBUS_OBJECT (config));
+ g_object_notify ((GObject *) self, NM_ACTIVE_CONNECTION_IP6_CONFIG);
+ }
+#endif
nm_vpn_connection_config_maybe_complete(self, TRUE);
}
@@ -2820,8 +2829,6 @@ dispose(GObject *object)
nm_clear_pointer(&priv->connect_hash, g_variant_unref);
- nm_clear_pointer(&priv->ip4_dev_route_blacklist, g_ptr_array_unref);
-
nm_clear_g_source(&priv->connect_timeout);
dispatcher_cleanup(self);
diff --git a/tools/run-nm-test.sh b/tools/run-nm-test.sh
index 81b94ec648..355a436600 100755
--- a/tools/run-nm-test.sh
+++ b/tools/run-nm-test.sh
@@ -362,7 +362,6 @@ if [ $HAS_ERRORS -eq 0 ]; then
# valgrind doesn't support setns syscall and spams the logfile.
# hack around it...
case "$TEST_NAME" in
- 'test-acd' | \
'test-address-linux' | \
'test-cleanup-linux' | \
'test-config' | \