summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-08-06 15:17:05 +0200
committerThomas Haller <thaller@redhat.com>2021-08-06 22:00:35 +0200
commitd348ed0e8016e586d6fe76c164467408a2acc051 (patch)
tree2772de99e93a8183a223ad94ce38dce46fe6cad9
parent170acd3ff465613047f2298085235596a2c2b3ce (diff)
downloadNetworkManager-th/l3cfg-22.tar.gz
core: use NML3ConfigData (WIP)th/l3cfg-22
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am20
-rw-r--r--WIP.txt13
-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.c497
-rw-r--r--src/core/devices/nm-acd-manager.h34
-rw-r--r--src/core/devices/nm-device-bond.c1
-rw-r--r--src/core/devices/nm-device-dummy.c1
-rw-r--r--src/core/devices/nm-device-ethernet.c40
-rw-r--r--src/core/devices/nm-device-infiniband.c1
-rw-r--r--src/core/devices/nm-device-ip-tunnel.c1
-rw-r--r--src/core/devices/nm-device-macvlan.c1
-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-tun.c1
-rw-r--r--src/core/devices/nm-device-vlan.c2
-rw-r--r--src/core/devices/nm-device-vxlan.c1
-rw-r--r--src/core/devices/nm-device-wireguard.c74
-rw-r--r--src/core/devices/nm-device-wpan.c1
-rw-r--r--src/core/devices/nm-device.c5288
-rw-r--r--src/core/devices/nm-device.h25
-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/team/nm-device-team.c1
-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.c28
-rw-r--r--src/core/devices/wifi/nm-device-wifi.c11
-rw-r--r--src/core/devices/wwan/nm-device-modem.c108
-rw-r--r--src/core/devices/wwan/nm-modem-broadband.c260
-rw-r--r--src/core/devices/wwan/nm-modem-ofono.c121
-rw-r--r--src/core/devices/wwan/nm-modem.c377
-rw-r--r--src/core/devices/wwan/nm-modem.h42
-rw-r--r--src/core/dhcp/README.md43
-rw-r--r--src/core/dhcp/nm-dhcp-client.c439
-rw-r--r--src/core/dhcp/nm-dhcp-client.h69
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.c1
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c4
-rw-r--r--src/core/dhcp/nm-dhcp-manager.c16
-rw-r--r--src/core/dhcp/nm-dhcp-manager.h5
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c241
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c263
-rw-r--r--src/core/dhcp/nm-dhcp-utils.c299
-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/dns/nm-dns-dnsmasq.c33
-rw-r--r--src/core/dns/nm-dns-manager.c539
-rw-r--r--src/core/dns/nm-dns-manager.h18
-rw-r--r--src/core/dns/nm-dns-systemd-resolved.c64
-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.build4
-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-connectivity.c1
-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.c181
-rw-r--r--src/core/nm-dispatcher.h8
-rw-r--r--src/core/nm-iface-helper.c13
-rw-r--r--src/core/nm-ip-config.c459
-rw-r--r--src/core/nm-ip-config.h45
-rw-r--r--src/core/nm-ip4-config.c3322
-rw-r--r--src/core/nm-ip4-config.h670
-rw-r--r--src/core/nm-ip6-config.c2689
-rw-r--r--src/core/nm-ip6-config.h206
-rw-r--r--src/core/nm-l3-config-data.c2
-rw-r--r--src/core/nm-l3cfg.c13
-rw-r--r--src/core/nm-manager.c2
-rw-r--r--src/core/nm-pacrunner-manager.c94
-rw-r--r--src/core/nm-pacrunner-manager.h7
-rw-r--r--src/core/nm-policy.c319
-rw-r--r--src/core/nm-proxy-config.c172
-rw-r--r--src/core/nm-proxy-config.h41
-rw-r--r--src/core/nm-types.h3
-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.c174
-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/tests/test-ip4-config.c1
-rw-r--r--src/core/tests/test-ip6-config.c2
-rw-r--r--src/core/vpn/nm-vpn-connection.c713
-rw-r--r--src/core/vpn/nm-vpn-connection.h4
-rw-r--r--src/libnm-systemd-core/meson.build2
-rw-r--r--src/libnm-systemd-core/nm-sd.h1
-rwxr-xr-xtools/run-nm-test.sh1
93 files changed, 5490 insertions, 14334 deletions
diff --git a/.gitignore b/.gitignore
index 25c60b1270..40d74286fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -240,7 +240,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
@@ -406,6 +405,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 8f658b52c0..65a25afe96 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2312,8 +2312,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp-lease.c \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-client.c \
src/libnm-systemd-core/src/libsystemd-network/sd-dhcp6-lease.c \
- src/libnm-systemd-core/src/libsystemd-network/sd-ipv4acd.c \
- src/libnm-systemd-core/src/libsystemd-network/sd-ipv4ll.c \
src/libnm-systemd-core/src/libsystemd-network/sd-lldp.c \
src/libnm-systemd-core/src/libsystemd/sd-event/event-source.h \
src/libnm-systemd-core/src/libsystemd/sd-event/event-util.c \
@@ -2331,8 +2329,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
src/libnm-systemd-core/src/systemd/sd-dhcp6-option.h \
src/libnm-systemd-core/src/systemd/sd-event.h \
src/libnm-systemd-core/src/systemd/sd-id128.h \
- src/libnm-systemd-core/src/systemd/sd-ipv4acd.h \
- src/libnm-systemd-core/src/systemd/sd-ipv4ll.h \
src/libnm-systemd-core/src/systemd/sd-lldp.h \
src/libnm-systemd-core/src/systemd/sd-ndisc.h \
$(NULL)
@@ -2380,10 +2376,6 @@ src_core_libNetworkManagerBase_la_SOURCES = \
src/core/nm-l3cfg.h \
src/core/nm-ip-config.c \
src/core/nm-ip-config.h \
- src/core/nm-ip4-config.c \
- src/core/nm-ip4-config.h \
- src/core/nm-ip6-config.c \
- src/core/nm-ip6-config.h \
\
src/core/dhcp/nm-dhcp-client.c \
src/core/dhcp/nm-dhcp-client.h \
@@ -2422,8 +2414,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-utils.c \
@@ -2572,8 +2562,6 @@ src_core_libNetworkManager_la_SOURCES = \
src/core/nm-firewall-utils.h \
src/core/nm-firewalld-manager.c \
src/core/nm-firewalld-manager.h \
- src/core/nm-proxy-config.c \
- src/core/nm-proxy-config.h \
src/core/nm-auth-manager.c \
src/core/nm-auth-manager.h \
src/core/nm-auth-utils.c \
@@ -4276,20 +4264,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..688cb6785f
--- /dev/null
+++ b/WIP.txt
@@ -0,0 +1,13 @@
+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-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 adcf878523..4bb1cc363e 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 8f4ceba75e..67c1476c2e 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 c041163ef8..0000000000
--- a/src/core/devices/nm-acd-manager.c
+++ /dev/null
@@ -1,497 +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;
- char buf[ETH_ALEN * 3];
-
- 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 (hw-addr %s)",
- _nm_utils_inet4_ntop(info->address, address_str),
- _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf)));
- }
- }
- 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_add_source(fd, G_IO_IN, acd_event, self);
-
- 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;
- char buf[ETH_ALEN * 3];
-
- 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 (hw-addr %s)",
- _nm_utils_inet4_ntop(info->address, sbuf),
- _nm_utils_hwaddr_ntoa(self->hwaddr, ETH_ALEN, TRUE, buf, sizeof(buf)));
- }
- }
-
- if (!self->event_source) {
- n_acd_get_fd(self->acd, &fd);
- self->event_source = nm_g_unix_fd_add_source(fd, G_IO_IN, acd_event, self);
- }
-
- 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-bond.c b/src/core/devices/nm-device-bond.c
index 4cd29e1478..48b41fad88 100644
--- a/src/core/devices/nm-device-bond.c
+++ b/src/core/devices/nm-device-bond.c
@@ -15,7 +15,6 @@
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-ip4-config.h"
#define _NMLOG_DEVICE_TYPE NMDeviceBond
#include "nm-device-logging.h"
diff --git a/src/core/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c
index c2b9dbab68..8d82baade5 100644
--- a/src/core/devices/nm-device-dummy.c
+++ b/src/core/devices/nm-device-dummy.c
@@ -12,7 +12,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-dummy.h"
diff --git a/src/core/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c
index 305552f074..153938ba40 100644
--- a/src/core/devices/nm-device-ethernet.c
+++ b/src/core/devices/nm-device-ethernet.c
@@ -17,7 +17,6 @@
#include "libnm-glib-aux/nm-uuid.h"
#include "nm-device-private.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "NetworkManagerUtils.h"
#include "supplicant/nm-supplicant-manager.h"
#include "supplicant/nm-supplicant-interface.h"
@@ -1136,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
@@ -1164,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,
@@ -1197,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;
}
@@ -1496,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-infiniband.c b/src/core/devices/nm-device-infiniband.c
index 37065bc89f..5c3064468e 100644
--- a/src/core/devices/nm-device-infiniband.c
+++ b/src/core/devices/nm-device-infiniband.c
@@ -13,7 +13,6 @@
#include "NetworkManagerUtils.h"
#include "nm-device-private.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "libnm-core-intern/nm-core-internal.h"
diff --git a/src/core/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c
index c55dd9f6b2..7f3c0b44f6 100644
--- a/src/core/devices/nm-device-ip-tunnel.c
+++ b/src/core/devices/nm-device-ip-tunnel.c
@@ -21,7 +21,6 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#define _NMLOG_DEVICE_TYPE NMDeviceIPTunnel
#include "nm-device-logging.h"
diff --git a/src/core/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c
index 7302ecdf2d..87c18ebe3d 100644
--- a/src/core/devices/nm-device-macvlan.c
+++ b/src/core/devices/nm-device-macvlan.c
@@ -18,7 +18,6 @@
#include "nm-setting-macvlan.h"
#include "nm-setting-wired.h"
#include "nm-active-connection.h"
-#include "nm-ip4-config.h"
#include "nm-utils.h"
#define _NMLOG_DEVICE_TYPE NMDeviceMacvlan
diff --git a/src/core/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c
index 8df245bb0f..c593459685 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 b55e8b4380..e2b2dd9693 100644
--- a/src/core/devices/nm-device-private.h
+++ b/src/core/devices/nm-device-private.h
@@ -34,8 +34,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);
@@ -66,8 +64,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);
@@ -109,9 +106,6 @@ nm_device_activate_ip6_state_done(NMDevice *self)
return nm_device_activate_get_ip_state(self, AF_INET6) == NM_DEVICE_IP_STATE_DONE;
}
-gboolean nm_device_dhcp4_renew(NMDevice *device, gboolean release);
-gboolean nm_device_dhcp6_renew(NMDevice *device, gboolean release);
-
void nm_device_recheck_available_connections(NMDevice *device);
void
@@ -126,7 +120,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);
@@ -137,12 +131,6 @@ 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, NMIPConfigSource source);
/*****************************************************************************/
diff --git a/src/core/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c
index ebccddfcf8..e622b7a87c 100644
--- a/src/core/devices/nm-device-tun.c
+++ b/src/core/devices/nm-device-tun.c
@@ -13,7 +13,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-tun.h"
diff --git a/src/core/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c
index 548245f80c..c989dbabc5 100644
--- a/src/core/devices/nm-device-vlan.c
+++ b/src/core/devices/nm-device-vlan.c
@@ -15,7 +15,6 @@
#include "nm-device-private.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-manager.h"
@@ -112,7 +111,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-vxlan.c b/src/core/devices/nm-device-vxlan.c
index f9dfad2a82..035acf873b 100644
--- a/src/core/devices/nm-device-vxlan.c
+++ b/src/core/devices/nm-device-vxlan.c
@@ -16,7 +16,6 @@
#include "nm-setting-wired.h"
#include "settings/nm-settings.h"
#include "nm-act-request.h"
-#include "nm-ip4-config.h"
#include "libnm-core-intern/nm-core-internal.h"
#define _NMLOG_DEVICE_TYPE NMDeviceVxlan
diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c
index aa9c46eba6..d83ef3d071 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_IP_CONFIG_SOURCE_USER);
+ 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-wpan.c b/src/core/devices/nm-device-wpan.c
index 73d7941001..2486f18c2d 100644
--- a/src/core/devices/nm-device-wpan.c
+++ b/src/core/devices/nm-device-wpan.c
@@ -14,7 +14,6 @@
#include "nm-act-request.h"
#include "nm-device-private.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-device-factory.h"
#include "nm-setting-wpan.h"
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index 6ad05a95df..53d46b5a02 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -34,6 +34,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"
@@ -45,11 +46,9 @@
#include "dhcp/nm-dhcp-manager.h"
#include "dhcp/nm-dhcp-utils.h"
#include "nm-act-request.h"
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-pacrunner-manager.h"
#include "dnsmasq/nm-dnsmasq-manager.h"
+#include "nm-ip-config.h"
#include "nm-dhcp-config.h"
#include "nm-rfkill-manager.h"
#include "nm-firewall-utils.h"
@@ -66,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 "libnm-systemd-core/nm-sd.h"
#include "nm-lldp-listener.h"
@@ -86,19 +84,8 @@
#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;
-}
+//XXX: drop GRACE_PERIOD_MULTIPLIER or review it at least.
+#define GRACE_PERIOD_MULTIPLIER 2U
#define CARRIER_WAIT_TIME_MS 6000
#define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000
@@ -117,6 +104,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;
@@ -139,28 +133,41 @@ 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,
+ _L3_CONFIG_DATA_TYPE_ACD_ONLY,
} 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,
@@ -176,21 +183,61 @@ typedef enum {
FIREWALL_STATE_WAIT_IP_CONFIG,
} 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 enum _nm_packed {
+ /* DHCP is not started. */
+ DHCP_STATE_NONE,
+
+ /* NMDhcpClient is in SELECTING state (or retrying).
+ *
+ * SELECTING and FAILED are pretty similar. In both cases are we trying
+ * to get a lease, but for SELECTING we just started and expect to succeed,
+ * while for FAILED it seems we won't be able to get a lease (but maybe
+ * we will). */
+ DHCP_STATE_SELECTING,
+
+ /* We have a lease, but are currently performing ACD on the
+ * address. */
+ DHCP_STATE_PROBING,
+
+ /* ACD passed and we accept the lease. */
+ DHCP_STATE_BOUND,
+
+ /* ACD failed, lease timeout or timeout obtaining a lease. This is similar to
+ * DHCP_STATE_SELECTING in that we try to re-get a lease in the background.
+ * But we also might fail the connection as a whole in this event.
+ *
+ * In this case, we also might have the grace timer running. */
+ DHCP_STATE_FAILED,
+} DhcpState;
+
+static NM_UTILS_LOOKUP_STR_DEFINE(_dhcp_state_to_string,
+ DhcpState,
+ NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(NULL),
+ NM_UTILS_LOOKUP_STR_ITEM(DHCP_STATE_NONE, "none"),
+ NM_UTILS_LOOKUP_STR_ITEM(DHCP_STATE_SELECTING, "selecting"),
+ NM_UTILS_LOOKUP_STR_ITEM(DHCP_STATE_BOUND, "bound"),
+ NM_UTILS_LOOKUP_STR_ITEM(DHCP_STATE_PROBING, "probing"),
+ NM_UTILS_LOOKUP_STR_ITEM(DHCP_STATE_FAILED, "failed"), );
typedef struct {
NMDhcpClient *client;
NMDhcpConfig *config;
- gulong notify_sigid;
- guint grace_id;
- bool grace_pending : 1;
- bool was_active : 1;
+
+ /* This is the currently received lease. Note that when we get offered a
+ * lease by NMDhcpClient, we (maybe) first need to perform ACD and accept
+ * it first. Hence, this lease may not be the one that we currently configure
+ * in priv->l3cds. */
+ const NML3ConfigData *current_l3cd;
+
+ gulong notify_sigid;
+ DhcpState state;
} DhcpData;
+typedef struct {
+ NMIPConfig *ip_config;
+ GSource * async_source;
+} IPStateData;
+
struct _NMDeviceConnectivityHandle {
CList concheck_lst;
NMDevice * self;
@@ -234,8 +281,7 @@ typedef struct {
enum {
STATE_CHANGED,
AUTOCONNECT_ALLOWED,
- IP4_CONFIG_CHANGED,
- IP6_CONFIG_CHANGED,
+ L3CD_CHANGED,
IP6_PREFIX_DELEGATED,
IP6_SUBNET_NEEDED,
REMOVED,
@@ -260,6 +306,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,
@@ -293,8 +342,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;
@@ -308,22 +355,12 @@ 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];
- };
-
struct {
const char **arr;
guint len;
guint alloc;
} pending_actions;
- GSList *dad6_failed_addrs;
-
NMDBusTrackObjPath parent_device;
char *udi;
@@ -339,15 +376,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;
+
+ NMFirewallConfig *firewall_config;
int parent_ifindex;
@@ -370,9 +422,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;
@@ -386,6 +435,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 */
@@ -451,7 +502,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;
@@ -468,6 +519,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_;
};
@@ -497,15 +556,21 @@ 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;
bool ip_config_started : 1;
+ GSource *ac6_ndisc_grace_source;
+
char *current_stable_id;
union {
@@ -516,69 +581,18 @@ typedef struct _NMDevicePrivate {
GSource *ip_req_timeout_source_x[2];
};
- /* Proxy Configuration */
- 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;
+ IPStateData ip_state_data_6;
+ IPStateData ip_state_data_4;
};
- NMIPConfig *ip_config_x[2];
+ IPStateData ip_state_data_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;
NMNDiscDHCPLevel mode;
guint needed_prefixes;
} dhcp6;
@@ -602,24 +616,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;
NMFirewalldManager * fw_mgr;
NMFirewalldManagerCallId *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 {
@@ -632,17 +639,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;
@@ -651,8 +653,6 @@ typedef struct _NMDevicePrivate {
EthtoolState *ethtool_state;
- gboolean needs_ip6_subnet;
-
/* master interface for bridge/bond/team slave */
NMDevice *master;
gulong master_ready_id;
@@ -708,6 +708,8 @@ typedef struct _NMDevicePrivate {
bool mtu_force_set_done : 1;
+ bool needs_ip6_subnet : 1;
+
NMOptionBool promisc_reset;
} NMDevicePrivate;
@@ -717,59 +719,72 @@ 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 _dev_l3_cfg_commit(NMDevice *self, gboolean commit_now);
-static gboolean nm_device_set_ip_config(NMDevice * self,
- int addr_family,
- NMIPConfig *config,
- gboolean commit,
- GPtrArray * ip4_dev_route_blacklist);
-
-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);
-static guint _prop_get_ipv4_dad_timeout(NMDevice *self);
-
-static NMIP6Config *dad6_get_pending_addresses(NMDevice *self);
+static guint32 _prop_get_ipv4_dad_timeout(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 void
+_dev_dhcpx_cleanup(NMDevice *self, int addr_family, gboolean reset_dhcp_config, gboolean release);
+
+static gboolean _dev_dhcpx_set_state(NMDevice *self, int addr_family, DhcpState state);
+
+static void _dev_dhcpx_restart(NMDevice *self, int addr_family, gboolean release);
+
+static void _dev_dhcpx_handle_accept(NMDevice *self, int addr_family);
+
+static void _dev_dhcpx_handle_fail(NMDevice *self, int addr_family);
+
+static void _dev_dhcp4_notify_acd_result(NMDevice *self, const NML3AcdAddrInfo *addr_info);
+
+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,
@@ -779,8 +794,27 @@ 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 void check_ip_state(NMDevice *self, gboolean may_fail, gboolean full_state_update);
+static gboolean device_link_changed(gpointer user_data);
+
+/*****************************************************************************/
+
+#define _NMLOG_dhcp(level, addr_family, fmt, ...) \
+ G_STMT_START \
+ { \
+ const int _addr_family2 = (addr_family); \
+ \
+ _NMLOG(level, \
+ (_addr_family2 == AF_UNSPEC ? LOGD_DHCP : LOGD_DHCPX(NM_IS_IPv4(_addr_family2))), \
+ "dhcp%s: " fmt, \
+ nm_utils_addr_family_to_str(_addr_family2), \
+ ##__VA_ARGS__); \
+ } \
+ G_STMT_END
+
+#define _LOGT_dhcp(...) _NMLOG_dhcp(LOGL_TRACE, __VA_ARGS__)
+#define _LOGD_dhcp(...) _NMLOG_dhcp(LOGL_DEBUG, __VA_ARGS__)
+#define _LOGI_dhcp(...) _NMLOG_dhcp(LOGL_INFO, __VA_ARGS__)
+#define _LOGW_dhcp(...) _NMLOG_dhcp(LOGL_WARN, __VA_ARGS__)
/*****************************************************************************/
@@ -1308,7 +1342,7 @@ _prop_get_connection_lldp(NMDevice *self)
return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX;
}
-static guint
+static guint32
_prop_get_ipv4_dad_timeout(NMDevice *self)
{
NMConnection * connection;
@@ -1320,6 +1354,9 @@ _prop_get_ipv4_dad_timeout(NMDevice *self)
s_ip4 = nm_connection_get_setting_ip4_config(connection);
if (s_ip4)
timeout = nm_setting_ip_config_get_dad_timeout(s_ip4);
+
+ nm_assert(timeout >= -1 && timeout <= NM_SETTING_IP_CONFIG_DAD_TIMEOUT_MAX);
+
if (timeout >= 0)
return timeout;
@@ -1336,8 +1373,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);
@@ -2389,27 +2426,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, NMIPConfigSource source)
{
@@ -2424,98 +2440,32 @@ nm_device_create_l3_config_data(NMDevice *self, NMIPConfigSource source)
return nm_l3_config_data_new(nm_device_get_multi_index(self), ifindex, source);
}
-static void
-applied_config_clear(AppliedConfig *config)
-{
- g_clear_object(&config->current);
- g_clear_object(&config->orig);
-}
-
-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)
+static const NML3ConfigData *
+_dev_create_l3_config_data_from_connection(NMDevice *self, NMConnection *connection)
{
- if (config->orig)
- nm_ip_config_add_search(config->orig, new);
- else
- nm_assert(!config->current);
+ NML3ConfigData *l3cd;
+ int ifindex;
- 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_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);
}
/*****************************************************************************/
@@ -2561,6 +2511,7 @@ nm_device_sys_iface_state_set(NMDevice *self, NMDeviceSysIfaceState sys_iface_st
nm_device_sys_iface_state_to_str(priv->sys_iface_state),
nm_device_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.
@@ -2673,33 +2624,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)
{
@@ -2845,7 +2769,7 @@ ip_required_timeout_x(NMDevice *self, int addr_family)
"required-timeout expired for IPv%c",
nm_utils_addr_family_to_char(addr_family));
nm_clear_g_source_inst(&priv->ip_req_timeout_source_x[NM_IS_IPv4(addr_family)]);
- check_ip_state(self, FALSE, TRUE);
+ //XXX check_ip_state(self, FALSE, TRUE);
return G_SOURCE_CONTINUE;
}
@@ -2925,6 +2849,525 @@ _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);
+ int IS_IPv4;
+
+ if (addr_family == AF_UNSPEC) {
+ _set_ip_state_check(self, AF_INET);
+ _set_ip_state_check(self, AF_INET6);
+ return;
+ }
+
+ IS_IPv4 = NM_IS_IPv4(addr_family);
+
+ nm_clear_g_source_inst(&priv->ip_state_data_x[IS_IPv4].async_source);
+
+ if (IS_IPv4) {
+ //XXX
+ AddrMethodState addr_method_state_dhcp_4 = ADDR_METHOD_STATE_DISABLED;
+
+ if (priv->dhcp_data_4.client) {
+ /* DHCP is enabled. */
+ //XXX } else if (priv->dhcp_data_4.is_bad || !priv->l3cds[L3_CONFIG_DATA_TYPE_DHCP_4].d) {
+ //XXX /* the DHCP configuration is failed. */
+ //XXX addr_method_state_dhcp_4 = ADDR_METHOD_STATE_FAILED;
+ //XXX } else
+ //XXX 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 gboolean
+_set_ip_state_check_async_cb(NMDevice *self, int addr_family)
+{
+ _set_ip_state_check(self, addr_family);
+ return G_SOURCE_CONTINUE;
+}
+
+static gboolean
+_set_ip_state_check_async_cb_4(gpointer user_data)
+{
+ return _set_ip_state_check_async_cb(user_data, AF_INET);
+}
+
+static gboolean
+_set_ip_state_check_async_cb_6(gpointer user_data)
+{
+ return _set_ip_state_check_async_cb(user_data, AF_INET6);
+}
+
+static void
+_set_ip_state_check_async(NMDevice *self, int addr_family)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+
+ if (!priv->ip_state_data_x[IS_IPv4].async_source) {
+ priv->ip_state_data_x[IS_IPv4].async_source = nm_g_idle_add_source(
+ IS_IPv4 ? _set_ip_state_check_async_cb_4 : _set_ip_state_check_async_cb_6,
+ self);
+ }
+}
+
+/*****************************************************************************/
+
+static gpointer
+_dev_l3_config_data_tag_get(NMDevicePrivate *priv, L3ConfigDataType l3cd_type)
+{
+ nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < G_N_ELEMENTS(priv->l3cds));
+
+ return &priv->l3cds[l3cd_type];
+}
+
+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])
+ || nm_ptr_to_uintptr(tag) >= nm_ptr_to_uintptr(&priv->l3cds[G_N_ELEMENTS(priv->l3cds)]))
+ return _L3_CONFIG_DATA_TYPE_NONE;
+
+ d = ((typeof(priv->l3cds[0]) *) tag) - (&priv->l3cds[0]);
+
+ nm_assert(d >= 0);
+ nm_assert(d < _L3_CONFIG_DATA_TYPE_NUM);
+ nm_assert(tag == &priv->l3cds[d]);
+ nm_assert(tag == _dev_l3_config_data_tag_get(priv, d));
+ return d;
+}
+
+static L3ConfigDataType
+_dev_l3_config_data_acd_addr_info_to_type(NMDevice * self,
+ const NML3AcdAddrInfo *addr_info,
+ guint i_track_infos)
+{
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(addr_info);
+ nm_assert(i_track_infos < addr_info->n_track_infos);
+
+ return _dev_l3_config_data_tag_to_type(self, addr_info->track_infos[i_track_infos].tag);
+}
+
+//XXX
+_nm_unused static const NML3AcdAddrTrackInfo *
+_dev_l3_config_data_acd_addr_info_has_by_type(NMDevice * self,
+ const NML3AcdAddrInfo *addr_info,
+ L3ConfigDataType l3cd_type)
+{
+ guint i;
+
+ nm_assert(NM_IS_DEVICE(self));
+ nm_assert(addr_info);
+ nm_assert(_NM_INT_NOT_NEGATIVE(l3cd_type) && l3cd_type < _L3_CONFIG_DATA_TYPE_NUM);
+
+ for (i = 0; i < addr_info->n_track_infos; i++) {
+ if (l3cd_type == _dev_l3_config_data_acd_addr_info_to_type(self, addr_info, i))
+ return &addr_info->track_infos[i];
+ }
+ return NULL;
+}
+
+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(_NM_INT_NOT_NEGATIVE(type) && 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_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_DHCP_4:
+ /* For DHCP, we perform ACD separately, because we want to decline the
+ * lease in case of a conflict. */
+ *out_acd_timeout_msec = 0;
+ break;
+
+ case _L3_CONFIG_DATA_TYPE_NUM:
+ case _L3_CONFIG_DATA_TYPE_NONE:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ *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:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ *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:
+ case _L3_CONFIG_DATA_TYPE_ACD_ONLY:
+ *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,
+ _dev_l3_config_data_tag_get(priv, l3cd_type),
+ 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,
+ NMTernary commit_sync)
+{
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL;
+ gboolean changed = FALSE;
+
+ if (priv->l3cds[l3cd_type].d != l3cd) {
+ l3cd_old = 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 (priv->l3cds[l3cd_type].d) {
+ if (_dev_l3_register_l3cds_add_config(self, l3cd_type))
+ changed = TRUE;
+ }
+
+ if (l3cd_old && l3cd_old != priv->l3cds[l3cd_type].d) {
+ if (nm_l3cfg_remove_config(priv->l3cfg,
+ _dev_l3_config_data_tag_get(priv, l3cd_type),
+ l3cd_old))
+ changed = TRUE;
+ }
+ }
+
+ if (changed && commit_sync != NM_TERNARY_DEFAULT)
+ _dev_l3_cfg_commit(self, !!commit_sync);
+
+ 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 < (int) G_N_ELEMENTS(priv->l3cds); i++) {
+ if (!priv->l3cds[i].d)
+ continue;
+ if (!do_add) {
+ if (nm_l3cfg_remove_config(l3cfg,
+ _dev_l3_config_data_tag_get(priv, i),
+ 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, TRUE);
+
+ 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, gboolean commit_sync)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+
+ if (!priv->l3cfg)
+ return;
+
+ if (!commit_sync) {
+ nm_l3cfg_commit_on_idle_schedule(priv->l3cfg);
+ return;
+ }
+ 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_L3CD_CHANGED:
+ if (notify_data->l3cd_changed.commited) {
+ g_signal_emit(self,
+ signals[L3CD_CHANGED],
+ 0,
+ notify_data->l3cd_changed.l3cd_old,
+ notify_data->l3cd_changed.l3cd_new);
+ }
+ return;
+ case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT:
+ {
+ const NML3AcdAddrInfo *addr_info = &notify_data->acd_event.info;
+
+ if (addr_info->state <= NM_L3_ACD_ADDR_STATE_PROBING) {
+ /* still probing... */
+ return;
+ }
+
+ _dev_dhcp4_notify_acd_result(self, addr_info);
+
+ /* XXX: other types for ACD results for non-DHCPv4 sources we currently ignore. */
+ 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, FALSE);
+}
+
+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_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, FALSE);
+}
+
/*****************************************************************************/
const char *
@@ -2946,11 +3389,18 @@ 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)
+ if (ifindex < 0) {
+ nm_assert_not_reached();
ifindex = 0;
+ }
p_ifindex = is_ip_ifindex ? &priv->ip_ifindex_ : &priv->ifindex_;
@@ -2959,13 +3409,74 @@ _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_ip_config_take_and_unexport_on_idle(g_steal_pointer(&priv->ip_state_data_4.ip_config));
+ nm_ip_config_take_and_unexport_on_idle(g_steal_pointer(&priv->ip_state_data_6.ip_config));
+ if (priv->l3cfg) {
+ priv->ip_state_data_4.ip_config = nm_ip_config_new(AF_INET, priv->l3cfg, FALSE);
+ priv->ip_state_data_6.ip_config = nm_ip_config_new(AF_INET6, priv->l3cfg, FALSE);
+ }
+ _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, TRUE);
+
+ if (l3cfg_commit_type_old)
+ nm_l3cfg_commit_type_unregister(l3cfg_old, l3cfg_commit_type_old);
+
return TRUE;
}
@@ -3701,7 +4212,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);
@@ -3785,28 +4297,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)
@@ -3838,18 +4344,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 *
@@ -4404,14 +4902,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 *
@@ -4793,7 +5285,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;
}
@@ -4911,7 +5403,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;
@@ -4951,26 +5443,15 @@ 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)) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_FAILED);
- return;
- }
- }
- if (priv->dhcp_data_6.client) {
- if (!nm_device_dhcp6_renew(self, FALSE)) {
- nm_device_state_changed(self,
- NM_DEVICE_STATE_FAILED,
- NM_DEVICE_STATE_REASON_DHCP_FAILED);
- return;
- }
- }
- if (priv->ndisc) {
+ if (priv->dhcp_data_4.state != DHCP_STATE_NONE)
+ _dev_dhcpx_restart(self, AF_INET, FALSE);
+ if (priv->dhcp_data_6.state != DHCP_STATE_NONE)
+ _dev_dhcpx_restart(self, AF_INET6, FALSE);
+
+ if (priv->ac6_ndisc) {
/* FIXME: todo */
}
- if (priv->dnsmasq_manager) {
+ if (priv->shared4_dnsmasq_manager) {
/* FIXME: todo */
}
}
@@ -5106,10 +5587,6 @@ nm_device_set_carrier(NMDevice *self, gboolean carrier)
nm_device_remove_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
_carrier_wait_check_queued_act_request(self);
}
-
- /* Send ARP announcements if did not yet and have carrier. */
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_DONE && !priv->acd.announcing)
- nm_device_arp_announce(self);
} else {
if (priv->carrier_wait_id)
nm_device_add_pending_action(self, NM_PENDING_ACTION_CARRIER_WAIT, FALSE);
@@ -5241,82 +5718,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
@@ -5350,8 +5765,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;
@@ -5436,8 +5852,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);
}
@@ -5484,23 +5900,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, TRUE);
}
if (update_unmanaged_specs)
@@ -5522,8 +5930,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;
@@ -5586,13 +5995,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);
}
}
@@ -6043,8 +6451,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",
@@ -6190,9 +6596,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);
@@ -6288,9 +6691,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);
@@ -6879,6 +7279,9 @@ nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config)
g_return_if_fail(NM_IS_DEVICE(self));
+ _dev_dhcpx_cleanup(self, AF_INET, TRUE, FALSE);
+ _dev_dhcpx_cleanup(self, AF_INET6, TRUE, FALSE);
+
priv = NM_DEVICE_GET_PRIVATE(self);
if (priv->master) {
/* this is called when something externally messes with the slave or during shut-down.
@@ -6890,15 +7293,7 @@ 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);
- }
+ _dev_l3_register_l3cds(self, priv->l3cfg, FALSE, TRUE);
}
static gboolean
@@ -7156,22 +7551,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;
}
@@ -7225,7 +7634,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;
@@ -7329,11 +7739,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_state_data_4.ip_config);
+ //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_state_data_6.ip_config, _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());
@@ -7797,20 +8209,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,
@@ -8147,6 +8545,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);
@@ -8590,7 +8989,7 @@ activate_stage2_device_config(NMDevice *self)
lldp_setup(self, NM_TERNARY_DEFAULT);
- _commit_mtu(self, NULL);
+ _commit_mtu(self);
nm_device_activate_schedule_stage3_ip_config_start(self);
}
@@ -8625,1049 +9024,607 @@ 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;
-
- for (i = 0; data->configs && data->configs[i]; i++)
- g_object_unref(data->configs[i]);
- g_free(data->configs);
- g_slice_free(AcdData, data);
-}
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-static void
-ipv4_manual_method_apply(NMDevice *self, NMIP4Config **configs, gboolean success)
-{
- NMConnection *connection;
- const char * method;
+ priv->ll4_ipv4ll_failed = FALSE;
+ priv->ll4_ipv4ll_ready = FALSE;
- 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, FALSE);
}
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;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ NML3IPv4LLState ipv4ll_state = NM_L3_IPV4LL_STATE_UNKNOWN;
+ const NML3ConfigData *l3cd;
- g_assert(data);
- self = data->device;
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- 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);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_LL_4, l3cd, FALSE);
- 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);
-
- for (i = 0, addr_found = FALSE; configs[i]; i++) {
- if (nm_ip4_config_get_num_addresses(configs[i]) > 0) {
- addr_found = TRUE;
- break;
- }
- }
-
- 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);
-
- 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);
-
- for (i = 0; configs[i]; i++)
- g_object_unref(configs[i]);
- g_free(configs);
-
- return;
- }
-
- data = g_slice_new0(AcdData);
- data->configs = configs;
- data->callback = cb;
- data->device = self;
-
- 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);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ guint32 timeout_msec;
- 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_ll4_cleanup(self);
- r = nm_acd_manager_start_probe(acd_manager, timeout);
- if (r < 0) {
- _LOGW(LOGD_DEVICE, "acd probe failed");
+ timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ if (timeout_msec == 0)
+ timeout_msec = NM_ACD_TIMEOUT_RFC5227_MSEC;
- /* DAD could not be started, signal success */
- cb(self, configs, TRUE);
+ _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "ipv4ll: enabling");
- priv->acd.dad_list = g_slist_remove(priv->acd.dad_list, acd_manager);
- nm_acd_manager_free(acd_manager);
- }
+ 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;
}
/*****************************************************************************/
-/* IPv4LL stuff */
-static void
-ipv4ll_cleanup(NMDevice *self)
+static const char *
+_device_get_dhcp_anycast_address(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);
- }
+ NMDeviceClass *klass;
- nm_clear_g_source(&priv->ipv4ll_timeout);
-}
+ nm_assert(NM_IS_DEVICE(self));
-static NMIP4Config *
-ipv4ll_get_ip4_config(NMDevice *self, guint32 lla)
-{
- NMIP4Config * config = NULL;
- NMPlatformIP4Address address;
- NMPlatformIP4Route route;
+ klass = NM_DEVICE_GET_CLASS(self);
- config = nm_device_ip4_config_new(self);
- g_assert(config);
+ if (klass->get_dhcp_anycast_address)
+ return klass->get_dhcp_anycast_address(self);
- 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);
+ return NULL;
+}
- /* 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);
+/*****************************************************************************/
- return config;
-}
+#define _dev_dhcp4_acd_tag(priv) (&(priv)->dhcp_data_4.current_l3cd)
static void
-nm_device_handle_ipv4ll_event(sd_ipv4ll *ll, int event, void *data)
+_dev_dhcp4_notify_acd_result(NMDevice *self, const NML3AcdAddrInfo *addr_info)
{
- NMDevice * self = data;
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- struct in_addr address;
- NMIP4Config * config;
- int r;
-
- if (priv->act_request.obj == NULL)
- return;
-
- nm_assert(nm_streq(nm_device_get_effective_ip_config_method(self, AF_INET),
- NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL));
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const NML3AcdAddrTrackInfo *track_info;
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- 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;
- }
+ nm_assert(addr_info);
+ nm_assert(addr_info->state > NM_L3_ACD_ADDR_STATE_PROBING);
- 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;
- }
+ if (priv->dhcp_data_4.state != DHCP_STATE_PROBING)
+ return;
- 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;
- }
+ track_info =
+ nm_l3_acd_addr_info_find_track_info(addr_info, _dev_dhcp4_acd_tag(priv), NULL, NULL);
+ if (!track_info)
+ return;
- 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(priv->dhcp_data_4.client);
+ nm_assert(nm_dhcp_client_can_accept(priv->dhcp_data_4.client));
+ nm_assert(track_info->l3cd == priv->dhcp_data_4.current_l3cd);
- 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 (addr_info->state <= NM_L3_ACD_ADDR_STATE_USED) {
+ _LOGW_dhcp(AF_INET,
+ "IP address collision detected for %s",
+ _nm_utils_inet4_ntop(addr_info->addr, sbuf));
+ _dev_dhcpx_handle_fail(self, AF_INET);
+ return;
}
+
+ _dev_dhcpx_handle_accept(self, AF_INET);
}
static gboolean
-ipv4ll_timeout_cb(gpointer user_data)
+_dev_dhcpx_set_state(NMDevice *self, int addr_family, DhcpState state)
{
- NMDevice * self = NM_DEVICE(user_data);
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- if (priv->ipv4ll_timeout) {
- _LOGI(LOGD_AUTOIP4, "IPv4LL configuration timed out.");
- priv->ipv4ll_timeout = 0;
- ipv4ll_cleanup(self);
+ if (priv->dhcp_data_x[IS_IPv4].state == state)
+ return FALSE;
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF)
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET);
- }
+ _LOGD_dhcp(addr_family,
+ "set state '%s' (was '%s')",
+ _dhcp_state_to_string(state),
+ _dhcp_state_to_string(priv->dhcp_data_x[IS_IPv4].state));
- return FALSE;
+ priv->dhcp_data_x[IS_IPv4].state = state;
+ return TRUE;
}
-static NMActStageReturn
-ipv4ll_start(NMDevice *self)
+static void
+_dev_dhcpx_cleanup(NMDevice *self, int addr_family, gboolean full_cleanup, gboolean release)
{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- const struct ether_addr *addr;
- int ifindex, r;
- size_t addr_len;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- ipv4ll_cleanup(self);
+ _dev_dhcpx_set_state(self, addr_family, DHCP_STATE_NONE);
- 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;
+ if (full_cleanup && !IS_IPv4) {
+ priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
+ priv->dhcp6.needed_prefixes = 0;
}
- 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;
- }
+ if (full_cleanup)
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE);
- 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;
- }
+ nm_clear_l3cd(&priv->dhcp_data_x[IS_IPv4].current_l3cd);
- 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;
- }
+ if (priv->l3cfg)
+ nm_l3cfg_remove_config_all(priv->l3cfg, _dev_l3_config_data_tag_get(priv, IS_IPv4));
- 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;
- }
-
- 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;
+ 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].notify_sigid);
+ nm_dhcp_client_stop(priv->dhcp_data_x[IS_IPv4].client, release);
+ g_clear_object(&priv->dhcp_data_x[IS_IPv4].client);
}
- 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;
+ if (full_cleanup) {
+ if (nm_dbus_object_clear_and_unexport(&priv->dhcp_data_x[IS_IPv4].config))
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
}
- _LOGI(LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started");
-
- /* 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;
+ _set_ip_state_check_async(self, addr_family);
}
-/*****************************************************************************/
-
static void
-ensure_con_ip_config(NMDevice *self, int addr_family)
+_dev_dhcpx_handle_fail(NMDevice *self, int addr_family)
{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- NMIPConfig * con_ip_config;
- if (priv->con_ip_config_x[IS_IPv4])
- return;
+ _LOGT_dhcp(addr_family, "DHCP failing");
- connection = nm_device_get_applied_connection(self);
- if (!connection)
- return;
+ if (priv->dhcp_data_x[IS_IPv4].state == DHCP_STATE_PROBING)
+ nm_dhcp_client_decline(priv->dhcp_data_4.client, "acd failed", NULL);
- con_ip_config = nm_device_ip_config_new(self, addr_family);
+ _dev_dhcpx_set_state(self, addr_family, DHCP_STATE_FAILED);
- 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));
- }
+ nm_clear_l3cd(&priv->dhcp_data_x[IS_IPv4].current_l3cd);
- 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);
- }
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), NULL, FALSE);
+ if (priv->l3cfg)
+ nm_l3cfg_remove_config_all(priv->l3cfg, _dev_l3_config_data_tag_get(priv, IS_IPv4));
- priv->con_ip_config_x[IS_IPv4] = con_ip_config;
-}
+ if (priv->dhcp_data_x[IS_IPv4].config)
+ nm_dhcp_config_set_lease(priv->dhcp_data_x[IS_IPv4].config, NULL);
-/*****************************************************************************/
+ _set_ip_state_check_async(self, addr_family);
+}
-static const char *
-_device_get_dhcp_anycast_address(NMDevice *self)
+static void
+_dev_dhcpx_handle_accept(NMDevice *self, int addr_family)
{
- NMDeviceClass *klass;
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const NML3ConfigData *l3cd;
+ gs_free_error GError *error = NULL;
- nm_assert(NM_IS_DEVICE(self));
+ _dev_dhcpx_set_state(self, addr_family, DHCP_STATE_BOUND);
- klass = NM_DEVICE_GET_CLASS(self);
+ l3cd = priv->dhcp_data_x[IS_IPv4].current_l3cd;
- if (klass->get_dhcp_anycast_address)
- return klass->get_dhcp_anycast_address(self);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_DHCP_X(IS_IPv4), l3cd, FALSE);
- return NULL;
-}
+ nm_l3cfg_remove_config_all(priv->l3cfg, _dev_l3_config_data_tag_get(priv, IS_IPv4));
-static void
-dhcp4_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_dhcp_config_set_lease(priv->dhcp_data_x[IS_IPv4].config, l3cd);
- 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);
+ _dev_l3_cfg_commit(self, TRUE);
- 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.notify_sigid);
+ _dev_l3_notify_change(self, addr_family);
- if (cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED)
- nm_dhcp_client_stop(priv->dhcp_data_4.client, release);
+ _set_ip_state_check(self, addr_family);
- g_clear_object(&priv->dhcp_data_4.client);
- }
+ nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_X(IS_IPv4),
+ self,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
- if (priv->dhcp_data_4.config) {
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_4.config);
- _notify(self, PROP_DHCP4_CONFIG);
+ if (!nm_dhcp_client_accept(priv->dhcp_data_x[IS_IPv4].client, &error)) {
+ _LOGD_dhcp(addr_family, "accept failed: %s", error->message);
+ _dev_dhcpx_handle_fail(self, addr_family);
}
}
-static gboolean
-ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit)
+static void
+_dev_dhcpx_handle_probing(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);
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ guint32 acd_timeout_msec;
- if (nm_device_sys_iface_state_is_external(self))
- commit = FALSE;
+ if (!IS_IPv4)
+ goto handle_accept;
+
+ acd_timeout_msec = _prop_get_ipv4_dad_timeout(self);
+ if (acd_timeout_msec == 0)
+ goto handle_accept;
+
+ if (!nm_dhcp_client_can_accept(priv->dhcp_data_x[IS_IPv4].client))
+ goto handle_accept;
+
+ _dev_dhcpx_set_state(self, addr_family, DHCP_STATE_PROBING);
+ nm_l3cfg_add_config(priv->l3cfg,
+ _dev_dhcp4_acd_tag(priv),
+ TRUE,
+ priv->dhcp_data_x[IS_IPv4].current_l3cd,
+ _L3_CONFIG_DATA_TYPE_ACD_ONLY,
+ 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),
+ NM_L3_ACD_DEFEND_TYPE_ALWAYS,
+ acd_timeout_msec,
+ NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD);
+ nm_l3cfg_commit_on_idle_schedule(priv->l3cfg);
+ return;
- connection = nm_device_get_applied_connection(self);
+handle_accept:
+ _dev_dhcpx_handle_accept(self, addr_family);
+}
- /* Apply ignore-auto-routes and ignore-auto-dns settings */
- if (connection) {
- NMSettingIPConfig *s_ip;
+static void
+_dev_dhcpx_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
+{
+ NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ const int addr_family = nm_dhcp_client_get_addr_family(client);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
- 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);
+ nm_assert(notify_data);
+ nm_assert(priv->dhcp_data_x[IS_IPv4].state > DHCP_STATE_NONE);
+ nm_assert(client && priv->dhcp_data_x[IS_IPv4].client == client);
- /* 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);
+ switch (notify_data->notify_type) {
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED:
+ nm_assert(!IS_IPv4);
+ /* 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, notify_data->prefix_delegated.prefix);
+ return;
- if (!IS_IPv4) {
- NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG(s_ip);
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT:
+ /* XXX: here we also fail if we had a lease and it expired. Maybe,
+ * ipv[46].dhcp-timeout should only cover the time until we get
+ * a lease for the first time. How it is here, it means that a
+ * connection can fail after being connected successfully for a
+ * longer time. */
+ if (priv->dhcp_data_x[IS_IPv4].state != DHCP_STATE_FAILED) {
+ nm_assert(priv->dhcp_data_x[IS_IPv4].state == DHCP_STATE_SELECTING);
+ _LOGD_dhcp(addr_family,
+ "ipv%c.dhcp-timeout period expired",
+ nm_utils_addr_family_to_char(addr_family));
+ _dev_dhcpx_handle_fail(self, addr_family);
+ }
+ return;
- 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);
- }
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD:
+ /* XXX: like NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT, this does not
+ * apply only if we never got a lease, but also after being fully
+ * connected. We can also fail then. */
+ if (priv->dhcp_data_x[IS_IPv4].state != DHCP_STATE_FAILED) {
+ nm_assert(priv->dhcp_data_x[IS_IPv4].state == DHCP_STATE_SELECTING);
+ _LOGD_dhcp(addr_family, "it seems we won't get a valid lease");
+ _dev_dhcpx_handle_fail(self, addr_family);
}
- }
+ return;
- composite = nm_device_ip_config_new(self, addr_family);
+ case NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE:
+ nm_assert(NM_IN_SET(notify_data->lease_update.dhcp_state,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_DECLINED)
+ == (!!notify_data->lease_update.l3cd));
- if (!IS_IPv4) {
- nm_ip6_config_set_privacy(NM_IP6_CONFIG(composite),
- priv->ndisc ? priv->ndisc_use_tempaddr
- : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- }
+ _LOGD_dhcp(addr_family, "lease %s", notify_data->lease_update.l3cd ? "update" : "lost");
- init_ip_config_dns_priority(self, composite);
+ switch (notify_data->lease_update.dhcp_state) {
+ case NM_DHCP_CLIENT_STATE_WITH_LEASE_DECLINED:
+ nm_assert_not_reached();
+ /* fall-through */
+ case NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT:
+ case NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED:
+
+ nm_assert(NM_IS_L3_CONFIG_DATA(notify_data->lease_update.l3cd));
+ nm_assert(
+ ((notify_data->lease_update.dhcp_state == NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED)
+ && !nm_dhcp_client_can_accept(client))
+ || ((notify_data->lease_update.dhcp_state == NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT)
+ && nm_dhcp_client_can_accept(client)));
+
+ nm_l3_config_data_reset(&priv->dhcp_data_x[IS_IPv4].current_l3cd,
+ notify_data->lease_update.l3cd);
+ _dev_dhcpx_handle_probing(self, addr_family);
+ return;
+ case NM_DHCP_CLIENT_STATE_NO_LEASE:
+ case NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT:
+ if (priv->dhcp_data_x[IS_IPv4].state == DHCP_STATE_SELECTING) {
+ _dev_dhcpx_handle_fail(self, addr_family);
+ }
+ return;
+ }
- 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);
+ nm_assert_not_reached();
}
- 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);
- }
- }
+ nm_assert_not_reached();
+}
- if (commit) {
- gboolean v;
+/*****************************************************************************/
- 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;
- }
+static void
+_dev_dhcpx_start(NMDevice *self, int addr_family)
+{
+ const int 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_error GError *error = NULL;
+ const NMPlatformLink *pllink;
+ guint no_lease_timeout_sec;
+ int ifindex;
+ const char * str;
+ gboolean request_broadcast;
- /* Merge all the IP configs into the composite config */
+ nm_assert(priv->dhcp_data_x[IS_IPv4].state == DHCP_STATE_NONE);
+ nm_assert(priv->dhcp_data_x[IS_IPv4].client == NULL);
- 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));
- }
- }
+ _dev_dhcpx_set_state(self, addr_family, DHCP_STATE_SELECTING);
- 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(self)) {
+ nm_assert_not_reached();
+ goto out_fail;
}
- 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));
- }
+ connection = nm_device_get_applied_connection(self);
+ if (!connection) {
+ nm_assert_not_reached();
+ goto out_fail;
}
- 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->ext_ip_config_x[IS_IPv4])
- nm_ip_config_merge(composite,
- priv->ext_ip_config_x[IS_IPv4],
- NM_IP_CONFIG_MERGE_EXTERNAL,
- 0);
-
- /* 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));
- }
+ 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);
- 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);
- }
- }
+ ifindex = 0;
+ 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));
}
-
- /* 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));
+ if (ifindex <= 0) {
+ _LOGD(LOGD_DHCP6, "dhcp: cannot start DHCP without interface");
+ goto out_fail;
}
- if (commit) {
- gboolean is_vrf;
+ hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
- is_vrf = priv->master && nm_device_get_device_type(priv->master) == NM_DEVICE_TYPE_VRF;
-
- 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);
+ if (!IS_IPv4) {
+ if (!hwaddr) {
+ _LOGD(LOGD_DHCP6, "dhcp6: cannot start DHCP with no suitable interface");
+ goto out_fail;
}
}
- 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));
+ 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;
}
}
if (!IS_IPv4) {
- NMUtilsIPv6IfaceId iid;
+ if (!_dev_ll6_start(self, &ll_addr)) {
+ /* wait for the LL address to show up */
- 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);
+ /* FIXME(simple-dhcp): need to handle to restart DHCPv6, when we get an address.
+ * also problem: as we use NM_DHCP_CLIENT_NO_LEASE_TIMEOUT to track our grace-period,
+ * if we are waiting here for a LL, the timer is not yet ticking. Preferably,
+ * NMDhcpClient would do the waiting for us and we would only kick off the generate
+ * of a LL addr. */
+ XXX("check that DHCP gets restarted when we get a LL. Or better: move that to "
+ "NMDhcpClient.");
+ return;
}
}
- 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;
- }
+ no_lease_timeout_sec = _prop_get_ipvx_dhcp_timeout(self, addr_family);
- return success;
-}
+ 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;
-static gboolean
-dhcp4_lease_change(NMDevice *self, NMIP4Config *config, gboolean bound)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_free_error GError *error = NULL;
+ 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);
- g_return_val_if_fail(config, FALSE);
+ bcast_hwaddr = nmp_link_address_get_as_bytes(&pllink->l_broadcast);
- applied_config_init(&priv->dev_ip_config_4, config);
+ 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),
+ client_id,
+ no_lease_timeout_sec,
+ _device_get_dhcp_anycast_address(self),
+ NULL,
+ vendor_class_identifier,
+ reject_servers,
+ &error);
+ } else {
+ gs_unref_bytes GBytes *duid = NULL;
+ gboolean iaid_explicit;
+ guint32 iaid;
- if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) {
- _LOGW(LOGD_DHCP4, "failed to update IPv4 config for DHCP change.");
- return FALSE;
- }
+ iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_explicit);
+ duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, &enforce_duid);
- /* 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;
+ 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),
+ duid,
+ enforce_duid,
+ iaid,
+ iaid_explicit,
+ no_lease_timeout_sec,
+ _device_get_dhcp_anycast_address(self),
+ nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip)),
+ priv->dhcp6.needed_prefixes,
+ &error);
+ }
+
+ if (!priv->dhcp_data_x[IS_IPv4].client) {
+ _LOGW_dhcp(addr_family, "failure to start DHCP client: %s", error->message);
+ goto out_fail;
}
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_4, self, NULL, NULL, NULL, NULL);
-
- return TRUE;
-}
-
-static gboolean
-dhcp_grace_period_expired(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- priv->dhcp_data_x[IS_IPv4].grace_id = 0;
- priv->dhcp_data_x[IS_IPv4].grace_pending = FALSE;
+ priv->dhcp_data_x[IS_IPv4].notify_sigid = g_signal_connect(priv->dhcp_data_x[IS_IPv4].client,
+ NM_DHCP_CLIENT_NOTIFY,
+ G_CALLBACK(_dev_dhcpx_notify),
+ self);
- _LOGI(LOGD_DHCPX(IS_IPv4),
- "DHCPv%c: grace period expired",
- nm_utils_addr_family_to_char(addr_family));
-
- 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 */
+ if (!priv->dhcp_data_x[IS_IPv4].config) {
+ priv->dhcp_data_x[IS_IPv4].config = nm_dhcp_config_new(addr_family);
+ _notify(self, PROP_DHCPX_CONFIG(IS_IPv4));
+ } else
+ nm_dhcp_config_set_lease(priv->dhcp_data_x[IS_IPv4].config, NULL);
- return G_SOURCE_REMOVE;
-}
+ return;
-static gboolean
-dhcp_grace_period_expired_4(gpointer user_data)
-{
- return dhcp_grace_period_expired(user_data, AF_INET);
+out_fail:
+ _dev_dhcpx_handle_fail(self, addr_family);
}
-static gboolean
-dhcp_grace_period_expired_6(gpointer user_data)
-{
- return dhcp_grace_period_expired(user_data, AF_INET6);
-}
+/*****************************************************************************/
-static gboolean
-dhcp_grace_period_start(NMDevice *self, int addr_family)
+static void
+_dev_dhcpx_restart(NMDevice *self, int addr_family, gboolean release)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
const int IS_IPv4 = NM_IS_IPv4(addr_family);
- guint32 timeout;
-
- /* 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. */
- 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);
- }
-
- priv->dhcp_data_x[IS_IPv4].grace_pending = TRUE;
-
- return TRUE;
-}
-static void
-dhcp4_fail(NMDevice *self, NMDhcpState dhcp_state)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- _LOGD(LOGD_DHCP4,
- "DHCPv4 failed (ip_state %s, was_active %d)",
- nm_device_ip_state_to_str(priv->ip_state_4),
- priv->dhcp_data_4.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)
- 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;
-
- /* 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 (priv->dhcp_data_x[IS_IPv4].state != DHCP_STATE_NONE) {
+ _LOGI_dhcp(addr_family, "restarting%s", release ? " (release lease)" : "");
+ _dev_dhcpx_cleanup(self, addr_family, FALSE, release);
}
- if (dhcp_grace_period_start(self, AF_INET))
- goto clear_config;
-
- 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);
- }
+ _dev_dhcpx_start(self, addr_family);
}
static void
-dhcp4_dad_cb(NMDevice *self, NMIP4Config **configs, gboolean success)
+_dev_dhcp6_set_dhcp_level(NMDevice *self, NMNDiscDHCPLevel dhcp_level)
{
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 (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE && priv->dhcp6.needed_prefixes > 0)
+ dhcp_level = NM_NDISC_DHCP_LEVEL_OTHERCONF;
-static void
-dhcp4_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMIP4Config * manual;
- NMIP4Config ** configs;
- NMConnection * connection;
- NMDhcpState state;
- NMIP4Config * ip4_config;
- GHashTable * options;
-
- nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET);
- nm_assert(notify_data);
- nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED);
-
- state = notify_data->state_changed.dhcp_state;
- ip4_config = NM_IP4_CONFIG(notify_data->state_changed.ip_config);
- options = notify_data->state_changed.options;
-
- nm_assert(!ip4_config || NM_IS_IP4_CONFIG(ip4_config));
-
- _LOGD(LOGD_DHCP4, "new DHCPv4 client state %d", (int) 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
- */
- 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);
-
- if (priv->ip_state_4 == NM_DEVICE_IP_STATE_CONF) {
- connection = nm_device_get_applied_connection(self);
- g_assert(connection);
-
- 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));
-
- configs = g_new0(NMIP4Config *, 3);
- configs[0] = manual;
- configs[1] = g_object_ref(ip4_config);
-
- 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);
- }
- break;
- case NM_DHCP_STATE_TIMEOUT:
- dhcp4_fail(self, state);
- 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)
- break;
- /* fall-through */
- case NM_DHCP_STATE_DONE:
- case NM_DHCP_STATE_FAIL:
- case NM_DHCP_STATE_TERMINATED:
- dhcp4_fail(self, state);
- break;
- default:
- break;
- }
-}
-
-static NMActStageReturn
-dhcp4_start(NMDevice *self)
-{
- 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;
- NMConnection * connection;
- NMSettingConnection * s_con;
- GError * error = NULL;
- const NMPlatformLink * pllink;
- const char *const * reject_servers;
- gboolean request_broadcast;
- const char * str;
-
- connection = nm_device_get_applied_connection(self);
- g_return_val_if_fail(connection, FALSE);
-
- s_ip4 = nm_connection_get_setting_ip4_config(connection);
-
- 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);
-
- request_broadcast = FALSE;
+ if (priv->dhcp6.mode == dhcp_level)
+ return;
- 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);
+ _LOGD_dhcp(AF_INET6, "level: set to %s", nm_ndisc_dhcp_level_to_string(dhcp_level));
- 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;
- }
- }
-
- 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);
-
- g_warn_if_fail(priv->dhcp_data_4.client == NULL);
- 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),
- 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),
- _prop_get_connection_mud_url(self, s_con),
- client_id,
- _prop_get_ipvx_dhcp_timeout(self, AF_INET),
- _device_get_dhcp_anycast_address(self),
- NULL,
- vendor_class_identifier,
- reject_servers,
- &error);
- if (!priv->dhcp_data_4.client) {
- _LOGW(LOGD_DHCP4, "failure to start DHCP: %s", error->message);
- g_clear_error(&error);
- return NM_ACT_STAGE_RETURN_FAILURE;
+ if (dhcp_level == NM_NDISC_DHCP_LEVEL_NONE) {
+ _dev_dhcpx_cleanup(self, AF_INET6, TRUE, TRUE);
+ return;
}
- priv->dhcp_data_4.notify_sigid = g_signal_connect(priv->dhcp_data_4.client,
- NM_DHCP_CLIENT_NOTIFY,
- G_CALLBACK(dhcp4_notify),
- self);
-
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_4.was_active = TRUE;
-
- /* DHCP devices will be notified by the DHCP manager when stuff happens */
- return NM_ACT_STAGE_RETURN_POSTPONE;
+ priv->dhcp6.mode = dhcp_level;
+ _dev_dhcpx_restart(self, AF_INET6, TRUE);
}
-gboolean
-nm_device_dhcp4_renew(NMDevice *self, gboolean release)
+/*
+ * Called on the requesting interface when a subnet can't be obtained
+ * from known prefixes for a newly active shared connection.
+ */
+void
+nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- 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,
- };
+ if (priv->dhcp6.needed_prefixes == needed_prefixes)
+ return;
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(connection, NULL);
+ _LOGD(LOGD_IP6, "ipv6-pd: asking DHCPv6 for %u prefixes", needed_prefixes);
- 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;
+ priv->dhcp6.needed_prefixes = needed_prefixes;
- 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 (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_NONE) {
+ priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF;
+ _LOGD_dhcp(AF_INET6,
+ "level: set to %s",
+ nm_ndisc_dhcp_level_to_string(NM_NDISC_DHCP_LEVEL_OTHERCONF));
}
- config = nm_device_ip4_config_new(self);
- nm_ip4_config_add_address(config, &address);
-
- return config;
+ _dev_dhcpx_restart(self, AF_INET6, TRUE);
}
/*****************************************************************************/
@@ -9765,392 +9722,6 @@ have_any_ready_slaves(NMDevice *self)
}
/*****************************************************************************/
-/* DHCPv6 stuff */
-
-static void
-dhcp6_cleanup(NMDevice *self, CleanupType cleanup_type, gboolean release)
-{
- 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.notify_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
-dhcp6_lease_change(NMDevice *self)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingsConnection *settings_connection;
-
- if (!applied_config_get_current(&priv->dhcp6.ip6_config)) {
- _LOGW(LOGD_DHCP6, "failed to get DHCPv6 config for rebind");
- return FALSE;
- }
-
- 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;
- }
-
- nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP_CHANGE_6, self, NULL, NULL, NULL, NULL);
-
- return TRUE;
-}
-
-static void
-dhcp6_fail(NMDevice *self, NMDhcpState dhcp_state)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gboolean is_dhcp_managed;
-
- _LOGD(LOGD_DHCP6,
- "DHCPv6 failed (ip_state %s, was_active %d)",
- nm_device_ip_state_to_str(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_6 == NM_DEVICE_IP_STATE_FAIL)
- goto clear_config;
-
- is_dhcp_managed = (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED);
-
- 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;
-
- /* 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_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
-dhcp6_notify(NMDhcpClient *client, const NMDhcpClientNotifyData *notify_data, NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- gs_free char * event_id = NULL;
- NMDhcpState state;
- NMIP6Config * ip6_config;
- GHashTable * options;
-
- nm_assert(nm_dhcp_client_get_addr_family(client) == AF_INET6);
- nm_assert(notify_data);
-
- if (notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED) {
- /* 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, notify_data->prefix_delegated.prefix);
- return;
- }
-
- nm_assert(notify_data->notify_type == NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED);
-
- state = notify_data->state_changed.dhcp_state;
- ip6_config = NM_IP6_CONFIG(notify_data->state_changed.ip_config);
- options = notify_data->state_changed.options;
-
- nm_assert(!ip6_config || NM_IS_IP6_CONFIG(ip6_config));
-
- _LOGD(LOGD_DHCP6, "new DHCPv6 client state %d", (int) state);
-
- switch (state) {
- case NM_DHCP_STATE_BOUND:
- case NM_DHCP_STATE_EXTENDED:
- 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.
- */
-
- event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
-
- if (ip6_config && event_id && priv->dhcp6.event_id
- && nm_streq(event_id, priv->dhcp6.event_id)) {
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *a;
-
- 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);
- }
-
- /* 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);
-
- 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:
- 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_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:
- dhcp6_fail(self, state);
- break;
- default:
- break;
- }
-}
-
-/*****************************************************************************/
-
-static gboolean
-dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection)
-{
- NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
- NMSettingIPConfig *s_ip6;
- gs_unref_bytes GBytes *hwaddr = NULL;
- gs_unref_bytes GBytes * duid = NULL;
- gboolean enforce_duid = FALSE;
- const NMPlatformLink * pllink;
- GError * error = NULL;
- guint32 iaid;
- gboolean iaid_explicit;
- NMSettingConnection * s_con;
- const NMPlatformIP6Address *ll_addr = NULL;
- int ip_ifindex;
-
- g_return_val_if_fail(connection, FALSE);
-
- 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);
-
- if (priv->ext_ip6_config_captured) {
- ll_addr = nm_ip_config_find_first_address(NM_IP_CONFIG(priv->ext_ip6_config_captured),
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
- }
-
- if (!ll_addr) {
- _LOGW(LOGD_DHCP6, "can't start DHCPv6: no link-local address");
- return FALSE;
- }
-
- ip_ifindex = nm_device_get_ip_ifindex(self);
- if (ip_ifindex <= 0) {
- _LOGD(LOGD_DHCP6, "can't start DHCPv6: interface is gone");
- return FALSE;
- }
-
- pllink = nm_platform_link_get(nm_device_get_platform(self), ip_ifindex);
- if (pllink)
- hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address);
-
- iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, TRUE, &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),
- ip_ifindex,
- &ll_addr->address,
- nm_connection_get_uuid(connection),
- 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),
- duid,
- enforce_duid,
- iaid,
- iaid_explicit,
- _prop_get_ipvx_dhcp_timeout(self, AF_INET6),
- _device_get_dhcp_anycast_address(self),
- nm_setting_ip6_config_get_ip6_privacy(NM_SETTING_IP6_CONFIG(s_ip6)),
- priv->dhcp6.needed_prefixes,
- &error);
- if (!priv->dhcp_data_6.client) {
- _LOGW(LOGD_DHCP6, "failure to start DHCPv6: %s", error->message);
- g_clear_error(&error);
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_6.was_active = TRUE;
- return FALSE;
- }
-
- priv->dhcp_data_6.notify_sigid = g_signal_connect(priv->dhcp_data_6.client,
- NM_DHCP_CLIENT_NOTIFY,
- G_CALLBACK(dhcp6_notify),
- self);
-
- if (nm_device_sys_iface_state_is_external_or_assume(self))
- priv->dhcp_data_6.was_active = TRUE;
-
- return TRUE;
-}
-
-static gboolean
-dhcp6_start(NMDevice *self, gboolean wait_for_ll)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMConnection * connection;
-
- nm_dbus_object_clear_and_unexport(&priv->dhcp_data_6.config);
- priv->dhcp_data_6.config = nm_dhcp_config_new(AF_INET6);
-
- 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);
-
- connection = nm_device_get_applied_connection(self);
- g_return_val_if_fail(connection, FALSE);
-
- 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 */
- }
-
- if (!dhcp6_start_with_link_ready(self, connection))
- return FALSE;
-
- return TRUE;
-}
-
-gboolean
-nm_device_dhcp6_renew(NMDevice *self, gboolean release)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- NMNDiscDHCPLevel mode;
-
- g_return_val_if_fail(priv->dhcp_data_6.client != NULL, FALSE);
-
- _LOGI(LOGD_DHCP6, "DHCPv6 lease renewal requested");
-
- /* Terminate old DHCP instance and release the old lease */
- mode = priv->dhcp6.mode;
- dhcp6_cleanup(self, CLEANUP_TYPE_DECONFIGURE, release);
- priv->dhcp6.mode = mode;
-
- /* Start DHCP again on the interface */
- return dhcp6_start(self, FALSE);
-}
-
-/*****************************************************************************/
-
-/*
- * Called on the requesting interface when a subnet can't be obtained
- * from known prefixes for a newly active shared connection.
- */
-void
-nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- priv->dhcp6.needed_prefixes = 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);
- } else {
- priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_OTHERCONF;
- _LOGD(LOGD_DEVICE | LOGD_DHCP6, "ipv6-pd: starting DHCPv6 to request a prefix");
- dhcp6_start(self, FALSE);
- }
-}
gboolean
nm_device_needs_ip6_subnet(NMDevice *self)
@@ -10165,25 +9736,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, NM_IP_CONFIG_SOURCE_SHARED);
/* 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, FALSE);
+ _dev_l3_cfg_commit(self, TRUE);
}
/*
@@ -10193,41 +9763,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;
+
+ /* FIXME(l3fcg): this entire code an approach seems flawed. It's flawed, because the
+ * very next RA will reset the changes. */
- 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);
+ 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, NM_IP_CONFIG_SOURCE_SHARED);
- 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, FALSE);
+
+ _dev_l3_cfg_commit(self, TRUE);
}
/*****************************************************************************/
static void
-linklocal6_failed(NMDevice *self)
+_dev_ll6_failed(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -10236,17 +9812,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;
@@ -10257,18 +9834,18 @@ linklocal6_check_complete(NMDevice *self)
return;
}
- if (!priv->ext_ip6_config_captured
- || !nm_ip_config_find_first_address(NM_IP_CONFIG(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);
@@ -10279,14 +9856,11 @@ 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)) {
- /* Time out IPv6 instead of failing the entire activation */
- nm_device_activate_schedule_ip_config_timeout(self, AF_INET6);
- }
+ _dev_dhcpx_start(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);
}
@@ -10305,17 +9879,18 @@ check_and_add_ipv6ll_addr(NMDevice *self)
if (!priv->ipv6ll_handle)
return;
- if (priv->ext_ip6_config_captured
- && nm_ip_config_find_first_address(NM_IP_CONFIG(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);
@@ -10339,7 +9914,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";
@@ -10350,7 +9925,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;
}
@@ -10368,21 +9943,37 @@ 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, TRUE);
}
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_ip_address_match(AF_INET6,
+ NMP_OBJECT_CAST_IP_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_ip_config_find_first_address(NM_IP_CONFIG(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 "
@@ -10396,7 +9987,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;
}
@@ -10560,13 +10151,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;
@@ -10574,7 +10168,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);
@@ -10588,8 +10184,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
@@ -10616,9 +10215,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;
}
@@ -10807,232 +10406,135 @@ 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);
- }
- }
-
- 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);
+ NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ int ifindex;
- 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, FALSE);
- 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, TRUE);
+}
- 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_ip_config_find_first_address(NM_IP_CONFIG(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;
if (!g_file_test("/proc/sys/net/ipv6", G_FILE_TEST_IS_DIR)) {
_LOGI(LOGD_IP6, "addrconf6: kernel does not support IPv6");
@@ -11040,16 +10542,17 @@ addrconf6_start(NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
}
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))
@@ -11072,28 +10575,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)) {
@@ -11102,32 +10607,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");
}
- /* already have the LL address; kick off neighbor discovery */
- addrconf6_start_with_link_ready(self);
+ _dev_l3_cfg_commit(self, TRUE);
+
+ 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);
+ }
+
+ 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;
+
+ 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);
- 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);
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_AC_6, NULL, FALSE);
+
+ if (priv->ac6_ndisc) {
+ nm_ndisc_stop(priv->ac6_ndisc);
+ g_clear_object(&priv->ac6_ndisc);
}
}
@@ -11249,10 +10780,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);
@@ -11301,52 +10832,31 @@ 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) {
- NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_DHCP_START_FAILED);
- return ret;
- }
- } else {
+ _dev_dhcpx_start(self, AF_INET);
+ } 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
@@ -11354,10 +10864,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");
@@ -11375,15 +10882,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;
@@ -11405,7 +10909,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
@@ -11419,59 +10923,36 @@ 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)) {
- /* IPv6 might be disabled; allow IPv4 to proceed */
- ret = NM_ACT_STAGE_RETURN_IP_FAIL;
- } else
- ret = NM_ACT_STAGE_RETURN_POSTPONE;
+ _dev_dhcpx_start(self, AF_INET6);
+ ret = NM_ACT_STAGE_RETURN_POSTPONE;
} else if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
ret = NM_ACT_STAGE_RETURN_SUCCESS;
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;
}
}
@@ -11479,13 +10960,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);
@@ -11497,22 +10978,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, FALSE);
+ 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);
@@ -11569,9 +11041,6 @@ 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);
-
check_ip_state(self, TRUE, TRUE);
}
@@ -11762,8 +11231,65 @@ 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_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->firewall_config) {
+ nm_firewall_config_apply(priv->firewall_config, FALSE);
+ nm_clear_pointer(&priv->firewall_config, nm_firewall_config_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",
@@ -11818,29 +11344,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;
- NMFirewallConfig * firewall_config;
-
- 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->firewall_config);
+ 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,
@@ -11848,15 +11382,18 @@ 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);
- firewall_config = nm_firewall_config_new(ip_iface, ip4_addr->address, ip4_addr->plen);
+ priv->firewall_config = nm_firewall_config_new(ip_iface, ip4_addr.address, ip4_addr.plen);
- nm_act_request_set_shared(req, firewall_config);
+ nm_firewall_config_apply(priv->firewall_config, TRUE);
conn = nm_act_request_get_applied_connection(req);
s_con = nm_connection_get_setting_connection(conn);
@@ -11881,8 +11418,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,
@@ -11890,81 +11429,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;
-}
-
-static void
-arp_cleanup(NMDevice *self)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
+ 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);
- 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;
+ _dev_l3_register_l3cds_set_one(self, L3_CONFIG_DATA_TYPE_SHARED_4, l3cd, FALSE);
- 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;
@@ -12020,7 +11507,7 @@ activate_stage5_ip_config_result_x(NMDevice *self, int addr_family)
if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) {
gs_free_error GError *error = NULL;
- if (!start_sharing(self, priv->ip_config_4, &error)) {
+ if (!start_sharing(self, priv->ip_state_data_4.ip_config, &error)) {
_LOGW(LOGD_SHARING,
"Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s",
error->message);
@@ -12108,6 +11595,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
@@ -12127,18 +11615,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.
@@ -12163,73 +11651,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
@@ -12268,21 +11689,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)
{
@@ -12374,26 +11780,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);
}
}
@@ -12483,37 +11877,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);
@@ -12532,58 +11895,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, TRUE);
}
static void
@@ -12593,11 +11905,11 @@ _pacrunner_manager_add(NMDevice *self)
nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
- priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
- priv->proxy_config,
- nm_device_get_ip_iface(self),
- NULL,
- NULL);
+ //XXX priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
+ //XXX priv->proxy_config,
+ //XXX nm_device_get_ip_iface(self),
+ //XXX NULL,
+ //XXX NULL);
}
static void
@@ -12607,7 +11919,6 @@ reactivate_proxy_config(NMDevice *self)
if (!priv->pacrunner_conf_id)
return;
- nm_device_set_proxy_config(self, priv->dhcp4.pac_url);
_pacrunner_manager_add(self);
}
@@ -12828,6 +12139,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
@@ -13087,96 +12399,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,
@@ -13559,321 +12781,53 @@ nm_device_is_activating(NMDevice *self)
return priv->activation_source_id_4 != 0;
}
-NMProxyConfig *
-nm_device_get_proxy_config(NMDevice *self)
-{
- g_return_val_if_fail(NM_IS_DEVICE(self), NULL);
-
- return NM_DEVICE_GET_PRIVATE(self)->proxy_config;
-}
-
-static void
-nm_device_set_proxy_config(NMDevice *self, const char *pac_url)
-{
- NMDevicePrivate *priv;
- NMConnection * connection;
- NMSettingProxy * s_proxy = NULL;
-
- g_return_if_fail(NM_IS_DEVICE(self));
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- g_clear_object(&priv->proxy_config);
- priv->proxy_config = nm_proxy_config_new();
-
- 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);
- _LOGD(LOGD_PROXY, "proxy: PAC url \"%s\"", pac_url);
- } else
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
-
- connection = nm_device_get_applied_connection(self);
- if (connection)
- s_proxy = nm_connection_get_setting_proxy(connection);
-
- if (s_proxy)
- 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);
- NMDeviceState state;
-
- nm_assert(!old || NM_IS_IP6_CONFIG(old));
- nm_assert(!old || nm_ip6_config_get_ifindex(old) > 0);
- nm_assert(!old || nm_device_get_ip_ifindex(self) == 0
- || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(old));
- nm_assert(!config || NM_IS_IP6_CONFIG(config));
- nm_assert(!config || nm_ip6_config_get_ifindex(config) > 0);
- nm_assert(!config || nm_device_get_ip_ifindex(self) == nm_ip6_config_get_ifindex(config));
-
- if (!_replace_vpn_config_in_list(&priv->vpn_configs_6, (GObject *) old, (GObject *) config))
- return;
+ if (!priv->l3cfg)
+ return NULL;
- state = nm_device_get_state(self);
- if (state >= NM_DEVICE_STATE_IP_CONFIG && state <= NM_DEVICE_STATE_ACTIVATED) {
- 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 int 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,
+ FALSE);
+ _dev_l3_cfg_commit(self, TRUE);
}
/*****************************************************************************/
static gboolean
-dispatcher_cleanup(NMDevice *self)
+_dispatcher_cleanup(NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
@@ -13887,7 +12841,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);
@@ -13907,7 +12861,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;
@@ -13915,11 +12869,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);
}
}
@@ -14111,17 +13065,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);
@@ -14261,15 +13219,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, TRUE);
return TRUE;
}
@@ -14332,381 +13282,6 @@ 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)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
- int ifindex;
- GSList * iter;
- gboolean is_up;
-
- nm_assert_addr_family(addr_family);
-
- ifindex = nm_device_get_ip_ifindex(self);
- if (!ifindex)
- return FALSE;
-
- is_up = nm_platform_link_is_up(nm_device_get_platform(self), ifindex);
-
- if (NM_IS_IPv4(addr_family)) {
- g_clear_object(&priv->ext_ip_config_4);
- priv->ext_ip_config_4 = nm_ip4_config_capture(nm_device_get_multi_index(self),
- nm_device_get_platform(self),
- ifindex);
- if (priv->ext_ip_config_4) {
- if (intersect_configs) {
- /* This function was called upon external changes. Remove the configuration
- * (addresses,routes) that is no longer present externally from the internal
- * config. This way, we don't re-add addresses that were manually removed
- * by the user. */
- if (priv->con_ip_config_4) {
- nm_ip4_config_intersect(priv->con_ip_config_4,
- priv->ext_ip_config_4,
- TRUE,
- is_up,
- default_route_metric_penalty_get(self, AF_INET));
- }
-
- intersect_ext_config(self, &priv->dev_ip_config_4, TRUE, is_up);
- intersect_ext_config(self, &priv->dev2_ip_config_4, TRUE, is_up);
-
- for (iter = priv->vpn_configs_4; iter; iter = iter->next)
- nm_ip4_config_intersect(iter->data, priv->ext_ip_config_4, TRUE, is_up, 0);
- }
-
- /* Remove parts from ext_ip_config_4 to only contain the information that
- * was configured externally -- we already have the same configuration from
- * internal origins. */
- if (priv->con_ip_config_4) {
- nm_ip4_config_subtract(priv->ext_ip_config_4,
- priv->con_ip_config_4,
- default_route_metric_penalty_get(self, AF_INET));
- }
- if (applied_config_get_current(&priv->dev_ip_config_4)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4,
- applied_config_get_current(&priv->dev_ip_config_4),
- default_route_metric_penalty_get(self, AF_INET));
- }
- if (applied_config_get_current(&priv->dev2_ip_config_4)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_4,
- applied_config_get_current(&priv->dev2_ip_config_4),
- default_route_metric_penalty_get(self, AF_INET));
- }
- for (iter = priv->vpn_configs_4; iter; iter = iter->next)
- nm_ip4_config_subtract(priv->ext_ip_config_4, iter->data, 0);
- }
-
- } else {
- nm_assert(!NM_IS_IPv4(addr_family));
-
- g_clear_object(&priv->ext_ip_config_6);
- 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),
- ifindex,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
- if (priv->ext_ip6_config_captured) {
- priv->ext_ip_config_6 = nm_ip6_config_new_cloned(priv->ext_ip6_config_captured);
-
- if (intersect_configs) {
- /* This function was called upon external changes. Remove the configuration
- * (addresses,routes) that is no longer present externally from the internal
- * config. This way, we don't re-add addresses that were manually removed
- * by the user. */
- if (priv->con_ip_config_6) {
- nm_ip6_config_intersect(priv->con_ip_config_6,
- priv->ext_ip_config_6,
- is_up,
- is_up,
- default_route_metric_penalty_get(self, AF_INET6));
- }
-
- intersect_ext_config(self, &priv->ac_ip6_config, is_up, is_up);
- intersect_ext_config(self, &priv->dhcp6.ip6_config, is_up, is_up);
- intersect_ext_config(self, &priv->dev2_ip_config_6, is_up, is_up);
-
- for (iter = priv->vpn_configs_6; iter; iter = iter->next)
- nm_ip6_config_intersect(iter->data, priv->ext_ip_config_6, is_up, is_up, 0);
-
- if (is_up && priv->ipv6ll_has
- && !nm_ip6_config_lookup_address(priv->ext_ip_config_6, &priv->ipv6ll_addr))
- priv->ipv6ll_has = FALSE;
- }
-
- /* Remove parts from ext_ip_config_6 to only contain the information that
- * was configured externally -- we already have the same configuration from
- * internal origins. */
- if (priv->con_ip_config_6) {
- nm_ip6_config_subtract(priv->ext_ip_config_6,
- priv->con_ip_config_6,
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->ac_ip6_config)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->ac_ip6_config),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->dhcp6.ip6_config)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->dhcp6.ip6_config),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- if (applied_config_get_current(&priv->dev2_ip_config_6)) {
- nm_ip_config_subtract((NMIPConfig *) priv->ext_ip_config_6,
- applied_config_get_current(&priv->dev2_ip_config_6),
- default_route_metric_penalty_get(self, AF_INET6));
- }
- for (iter = priv->vpn_configs_6; iter; iter = iter->next)
- nm_ip6_config_subtract(priv->ext_ip_config_6, iter->data, 0);
- }
- }
-
- return TRUE;
-}
-
-static void
-update_ip_config(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self);
-
- nm_assert_addr_family(addr_family);
-
- if (NM_IS_IPv4(addr_family))
- priv->update_ip_config_completed_v4 = TRUE;
- else
- priv->update_ip_config_completed_v6 = TRUE;
-
- if (update_ext_ip_config(self, addr_family, TRUE)) {
- if (NM_IS_IPv4(addr_family)) {
- if (priv->ext_ip_config_4)
- ip_config_merge_and_apply(self, AF_INET, FALSE);
- } else {
- if (priv->ext_ip6_config_captured)
- 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);
-}
-
-static gboolean
-queued_ip_config_change(NMDevice *self, int addr_family)
-{
- NMDevicePrivate *priv;
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
-
- g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE);
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- /* Wait for any queued state changes */
- if (priv->queued_state.id)
- return G_SOURCE_CONTINUE;
-
- /* If a commit is scheduled, this function would potentially interfere with
- * it changing IP configurations before they are applied. Postpone the
- * update in such case.
- */
- if (priv->activation_source_id_x[IS_IPv4] != 0
- && priv->activation_source_func_x[IS_IPv4]
- == activate_stage5_ip_config_result_x_fcn(addr_family))
- return G_SOURCE_CONTINUE;
-
- priv->queued_ip_config_id_x[IS_IPv4] = 0;
-
- update_ip_config(self, addr_family);
-
- if (!IS_IPv4) {
- /* Check whether we need to complete waiting for link-local.
- * We are also called from an idle handler, so no problem doing state transitions
- * now. */
- linklocal6_check_complete(self);
- }
-
- if (!IS_IPv4) {
- NMPlatform * platform;
- GSList * dad6_failed_addrs, *iter;
- const NMPlatformLink *pllink;
-
- dad6_failed_addrs = g_steal_pointer(&priv->dad6_failed_addrs);
-
- if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING
- && priv->ifindex > 0 && !nm_device_sys_iface_state_is_external(self)
- && (platform = nm_device_get_platform(self))
- && (pllink = nm_platform_link_get(platform, priv->ifindex))
- && (pllink->n_ifi_flags & IFF_UP)) {
- gboolean need_ipv6ll = FALSE;
- NMNDiscConfigMap ndisc_config_changed = NM_NDISC_CONFIG_NONE;
-
- /* Handle DAD failures */
- for (iter = dad6_failed_addrs; iter; iter = iter->next) {
- const NMPObject * obj = iter->data;
- const NMPlatformIP6Address *addr;
-
- if (!nm_ndisc_dad_addr_is_fail_candidate(platform, obj))
- continue;
-
- addr = NMP_OBJECT_CAST_IP6_ADDRESS(obj);
-
- _LOGI(LOGD_IP6,
- "ipv6: duplicate address check failed for the %s address",
- nm_platform_ip6_address_to_string(addr, NULL, 0));
-
- if (IN6_IS_ADDR_LINKLOCAL(&addr->address))
- need_ipv6ll = TRUE;
- else if (priv->ndisc)
- ndisc_config_changed |= nm_ndisc_dad_failed(priv->ndisc, &addr->address, FALSE);
- }
-
- if (ndisc_config_changed != NM_NDISC_CONFIG_NONE)
- nm_ndisc_emit_config_change(priv->ndisc, ndisc_config_changed);
-
- /* If no IPv6 link-local address exists but other addresses do then we
- * must add the LL address to remain conformant with RFC 3513 chapter 2.1
- * ("Addressing Model"): "All interfaces are required to have at least
- * one link-local unicast address".
- */
- if (priv->ip_config_6 && nm_ip6_config_get_num_addresses(priv->ip_config_6))
- need_ipv6ll = TRUE;
- if (need_ipv6ll)
- check_and_add_ipv6ll_addr(self);
- }
-
- g_slist_free_full(dad6_failed_addrs, (GDestroyNotify) nmp_object_unref);
- }
-
- if (!IS_IPv4) {
- /* Check if DAD is still pending */
- if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && priv->dad6_ip6_config
- && priv->ext_ip6_config_captured
- && !nm_ip6_config_has_any_dad_pending(priv->ext_ip6_config_captured,
- priv->dad6_ip6_config)) {
- _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD terminated");
- g_clear_object(&priv->dad6_ip6_config);
- _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE);
- check_ip_state(self, FALSE, TRUE);
- if (priv->rt6_temporary_not_available)
- nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL);
- }
- }
-
- set_unmanaged_external_down(self, TRUE);
-
- return G_SOURCE_REMOVE;
-}
-
-static gboolean
-queued_ip4_config_change(gpointer user_data)
-{
- return queued_ip_config_change(user_data, AF_INET);
-}
-
-static gboolean
-queued_ip6_config_change(gpointer user_data)
-{
- return queued_ip_config_change(user_data, AF_INET6);
-}
-
-static void
-device_ipx_changed(NMPlatform * platform,
- int obj_type_i,
- int ifindex,
- gconstpointer platform_object,
- int change_type_i,
- NMDevice * self)
-{
- const NMPObjectType obj_type = obj_type_i;
- const NMPlatformSignalChangeType change_type = change_type_i;
- NMDevicePrivate * priv;
- const NMPlatformIP6Address * addr;
-
- if (nm_device_get_ip_ifindex(self) != ifindex)
- return;
-
- if (!nm_device_is_real(self))
- return;
-
- if (nm_device_get_unmanaged_flags(self, NM_UNMANAGED_PLATFORM_INIT)) {
- /* ignore all platform signals until the link is initialized in platform. */
- return;
- }
-
- priv = NM_DEVICE_GET_PRIVATE(self);
-
- switch (obj_type) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- if (!priv->queued_ip_config_id_4) {
- priv->queued_ip_config_id_4 = g_idle_add(queued_ip4_config_change, self);
- _LOGD(LOGD_DEVICE, "queued IP4 config change");
- }
- break;
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- addr = platform_object;
-
- if (priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state < NM_DEVICE_STATE_DEACTIVATING
- && nm_ndisc_dad_addr_is_fail_candidate_event(change_type, addr)) {
- priv->dad6_failed_addrs =
- g_slist_prepend(priv->dad6_failed_addrs,
- (gpointer) nmp_object_ref(NMP_OBJECT_UP_CAST(addr)));
- }
-
- /* fall-through */
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- if (!priv->queued_ip_config_id_6) {
- priv->queued_ip_config_id_6 = g_idle_add(queued_ip6_config_change, self);
- _LOGD(LOGD_DEVICE, "queued IP6 config change");
- }
- break;
- default:
- g_return_if_reached();
- }
-}
-
/*****************************************************************************/
NM_UTILS_FLAGS2STR_DEFINE(nm_unmanaged_flags2str,
@@ -14959,12 +13534,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.len == 0) {
do_notify_has_pending_actions = TRUE;
had_pending_actions = nm_device_has_pending_action(self);
@@ -15316,9 +13885,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
@@ -15889,7 +14462,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 */
@@ -15924,7 +14497,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);
@@ -15947,6 +14520,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;
@@ -15956,40 +14530,12 @@ _cleanup_generic_post(NMDevice *self, CleanupType cleanup_type)
priv->linklocal6_dad_counter = 0;
- 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);
+ priv->ipv6ll_has = FALSE;
+ priv->ipv6ll_addr = nm_ip_addr_zero.addr6;
- 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;
+ priv->mtu_force_set_done = FALSE;
- /* We no longer accept the delegations. nm_device_set_ip_config(NULL)
- * above disables them. */
- nm_assert(priv->needs_ip6_subnet == FALSE);
+ priv->needs_ip6_subnet = FALSE;
if (priv->act_request.obj) {
nm_active_connection_set_default(NM_ACTIVE_CONNECTION(priv->act_request.obj),
@@ -16158,18 +14704,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
@@ -16181,7 +14728,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;
@@ -16226,10 +14772,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);
@@ -16238,8 +14783,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"));
@@ -16289,7 +14838,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"));
@@ -16340,23 +14889,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)
{
@@ -16495,9 +15027,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;
@@ -16507,8 +15039,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;
@@ -16545,14 +15076,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);
@@ -16759,9 +15290,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason,
_LOGI(LOGD_DEVICE, "Activation: successful, device activated.");
nm_device_update_metered(self);
nm_dispatcher_call_device(NM_DISPATCHER_ACTION_UP, self, req, NULL, NULL, NULL);
-
- if (priv->proxy_config)
- _pacrunner_manager_add(self);
+ _pacrunner_manager_add(self);
break;
case NM_DEVICE_STATE_FAILED:
/* Usually upon failure the activation chain is interrupted in
@@ -16821,11 +15350,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:
@@ -16848,18 +15372,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))
@@ -17926,39 +16445,16 @@ nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean
/* Determine the most suitable address of the interface
* and whether it changed from the previous lookup */
- ip_config = priv->ip_config_x[IS_IPv4];
+ ip_config = priv->ip_state_data_x[IS_IPv4].ip_config;
if (ip_config) {
- const NMPlatformIPAddress *addr = NULL;
-
- if (IS_IPv4) {
- addr = nm_ip_config_get_first_address(ip_config);
- } else {
- /* For IPv6 prefer, in order:
- * - !link-local, !deprecated
- * - !link-local, deprecated
- * - link-local
- */
- addr = nm_ip_config_find_first_address(ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_NORMAL);
- if (!addr) {
- addr = nm_ip_config_find_first_address(
- ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_NORMAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE_DEPRECATED);
- }
- if (!addr) {
- addr = nm_ip_config_find_first_address(ip_config,
- NM_PLATFORM_MATCH_WITH_ADDRTYPE_LINKLOCAL
- | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY);
- }
- }
+ //XXX const NMPlatformIPAddress *addr;
- if (addr) {
- new_address = g_inet_address_new_from_bytes(addr->address_ptr,
- IS_IPv4 ? G_SOCKET_FAMILY_IPV4
- : G_SOCKET_FAMILY_IPV6);
- }
+ //XXX addr = nm_ip_config_get_first_address(ip_config);
+ //XXX if (addr) {
+ //XXX new_address = g_inet_address_new_from_bytes(addr->address_ptr,
+ //XXX IS_IPv4 ? G_SOCKET_FAMILY_IPV4
+ //XXX : G_SOCKET_FAMILY_IPV6);
+ //XXX }
}
if (new_address && resolver->address) {
@@ -18068,13 +16564,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);
@@ -18109,24 +16602,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_state_data_4.ip_config);
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_state_data_6.ip_config);
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);
@@ -18437,24 +16922,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);
@@ -18506,15 +16974,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);
@@ -18592,7 +17057,6 @@ finalize(GObject *object)
g_free(priv->hw_addr_perm);
g_free(priv->hw_addr_initial);
g_free(priv->pending_actions.arr);
- 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);
@@ -19107,29 +17571,17 @@ nm_device_class_init(NMDeviceClass *klass)
G_TYPE_BOOLEAN,
0);
- signals[IP4_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP4_CONFIG_CHANGED,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT);
-
- signals[IP6_CONFIG_CHANGED] = g_signal_new(NM_DEVICE_IP6_CONFIG_CHANGED,
- G_OBJECT_CLASS_TYPE(object_class),
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL,
- NULL,
- NULL,
- G_TYPE_NONE,
- 2,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT);
+ signals[L3CD_CHANGED] = g_signal_new(NM_DEVICE_L3CD_CHANGED,
+ G_OBJECT_CLASS_TYPE(object_class),
+ G_SIGNAL_RUN_FIRST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_POINTER, /* (const NML3ConfigData *l3cd_old) */
+ G_TYPE_POINTER /* (const NML3ConfigData *l3cd_new) */);
signals[IP6_PREFIX_DELEGATED] =
g_signal_new(NM_DEVICE_IP6_PREFIX_DELEGATED,
diff --git a/src/core/devices/nm-device.h b/src/core/devices/nm-device.h
index f59b6fa845..4b76461cdf 100644
--- a/src/core/devices/nm-device.h
+++ b/src/core/devices/nm-device.h
@@ -70,8 +70,7 @@
/* Internal signals */
#define NM_DEVICE_DNS_LOOKUP_DONE "dns-lookup-done"
-#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
-#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
+#define NM_DEVICE_L3CD_CHANGED "l3cd-changed"
#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed"
#define NM_DEVICE_REMOVED "removed"
@@ -343,15 +342,16 @@ 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);
- void (*ip4_config_pre_commit)(NMDevice *self, NMIP4Config *config);
+ //XXX: needs rework to not use NMIP4Config.
+ void (*ip4_config_pre_commit)(NMDevice *self);
/* Async deactivating (in the DEACTIVATING phase) */
void (*deactivate_async)(NMDevice * self,
@@ -459,16 +459,11 @@ const char *nm_device_get_permanent_hw_address_full(NMDevice *self,
gboolean *out_is_fake);
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);
@@ -546,7 +541,7 @@ RfKillType nm_device_get_rfkill_type(NMDevice *device);
/* IPv6 prefix delegation */
-void nm_device_request_ip6_prefixes(NMDevice *self, int needed_prefixes);
+void nm_device_request_ip6_prefixes(NMDevice *self, guint needed_prefixes);
gboolean nm_device_needs_ip6_subnet(NMDevice *self);
diff --git a/src/core/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c
index 26a5ba002c..f18102cfe2 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 46a612aca7..ad04e9fea7 100644
--- a/src/core/devices/ovs/nm-device-ovs-interface.c
+++ b/src/core/devices/ovs/nm-device-ovs-interface.c
@@ -189,10 +189,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);
@@ -212,7 +212,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 f11c585235..be1a51be8d 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/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c
index 0f1a8c4cec..5fa16790d0 100644
--- a/src/core/devices/team/nm-device-team.c
+++ b/src/core/devices/team/nm-device-team.c
@@ -22,7 +22,6 @@
#include "nm-config.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-dbus-manager.h"
-#include "nm-ip4-config.h"
#include "libnm-std-aux/nm-dbus-compat.h"
#define _NMLOG_DEVICE_TYPE NMDeviceTeam
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 247a613080..f3159a52a9 100644
--- a/src/core/devices/wifi/nm-device-wifi-p2p.c
+++ b/src/core/devices/wifi/nm-device-wifi-p2p.c
@@ -14,17 +14,17 @@
#include "NetworkManagerUtils.h"
#include "devices/nm-device-private.h"
-#include "nm-act-request.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-glib-aux/nm-ref-string.h"
-#include "nm-ip4-config.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nmp-object.h"
+#include "nm-act-request.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
#include "nm-manager.h"
#include "nm-setting-wifi-p2p.h"
#include "nm-utils.h"
#include "nm-wifi-p2p-peer.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nmp-object.h"
#include "settings/nm-settings.h"
#define _NMLOG_DEVICE_TYPE NMDeviceWifiP2P
@@ -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)
{
NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE(device);
gboolean indicate_addressing_running;
@@ -576,17 +576,17 @@ act_stage3_ip_config_start(NMDevice * device,
guint8 plen;
if (nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, &addr, &plen)) {
- NMPlatformIP4Address address = {
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP4Address address = {
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
};
- gs_unref_object NMIP4Config *ip4_config = NULL;
nm_platform_ip4_address_set_addr(&address, addr, plen);
- ip4_config = nm_device_ip4_config_new(device);
- nm_ip4_config_add_address(ip4_config, &address);
+ l3cd = nm_device_create_l3_config_data(device, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_add_address_4(l3cd, &address);
- nm_device_set_dev2_ip_config(device, AF_INET, NM_IP_CONFIG(ip4_config));
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
/* This just disables the addressing indicator. */
method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
@@ -607,7 +607,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 8dde307762..30611db85e 100644
--- a/src/core/devices/wifi/nm-device-wifi.c
+++ b/src/core/devices/wifi/nm-device-wifi.c
@@ -31,7 +31,6 @@
#include "nm-setting-wireless-security.h"
#include "nm-setting-8021x.h"
#include "nm-setting-ip4-config.h"
-#include "nm-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-auth-utils.h"
@@ -3266,10 +3265,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;
@@ -3292,7 +3291,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 4d892e6f4e..e0a7648178 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,41 +189,37 @@ 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;
- if (!nm_device_activate_ip4_state_in_conf(device)) {
- _LOGD(LOGD_MB | LOGD_IP4,
- "retrieving IPv4 configuration while no longer in state IPv4 conf");
- return;
- }
+ 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);
+ 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;
+ }
+
+ nm_device_set_dev2_ip_config(device, AF_INET, l3cd);
+ nm_device_activate_schedule_ip_config_result(device, AF_INET);
return;
}
- 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);
-}
-
-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;
-
if (!nm_device_activate_ip6_state_in_conf(device)) {
_LOGD(LOGD_MB | LOGD_IP6,
"retrieving IPv6 configuration while no longer in state IPv6 conf");
@@ -235,15 +232,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");
@@ -255,11 +256,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:
@@ -267,7 +267,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 */
@@ -611,10 +611,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);
@@ -631,9 +631,9 @@ act_stage3_ip_config_start(NMDevice * device,
}
static void
-ip4_config_pre_commit(NMDevice *device, NMIP4Config *config)
+ip4_config_pre_commit(NMDevice *device)
{
- nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device, config);
+ nm_modem_ip4_pre_commit(NM_DEVICE_MODEM_GET_PRIVATE(device)->modem, device);
}
static gboolean
@@ -641,14 +641,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);
}
/*****************************************************************************/
@@ -714,8 +715,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..1bad9ba34e 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_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,114 @@ 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,
+ NM_IP_CONFIG_SOURCE_WWAN);
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 +1243,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..30c910af54 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,14 @@ 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_IP_CONFIG_SOURCE_WWAN);
if (!g_variant_lookup(v_dict, "Address", "&s", &s)) {
_LOGW("Settings 'Address' missing");
@@ -788,10 +790,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 +805,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 +818,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 +837,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 +919,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 +1041,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 +1259,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..397c2f580b 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 */
@@ -786,9 +806,11 @@ nm_modem_stage3_ip4_config_start(NMModem * self,
}
void
-nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config)
+nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device)
{
- 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
@@ -1767,11 +1682,7 @@ nm_modem_init(NMModem *self)
self->_priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_MODEM, NMModemPrivate);
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;
+ priv->ip_ifindex = -1;
}
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..95f66a8d6e 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);
@@ -217,7 +201,7 @@ NMActStageReturn nm_modem_stage3_ip6_config_start(NMModem * modem,
NMDevice * device,
NMDeviceStateReason *out_failure_reason);
-void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device, NMIP4Config *config);
+void nm_modem_ip4_pre_commit(NMModem *modem, NMDevice *device);
void nm_modem_get_secrets(NMModem * modem,
const char *setting_name,
@@ -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/README.md b/src/core/dhcp/README.md
new file mode 100644
index 0000000000..14c5ea8e5c
--- /dev/null
+++ b/src/core/dhcp/README.md
@@ -0,0 +1,43 @@
+`NMDhcpClient`
+==============
+
+Driving `NMDhcpClient` still requires a lot of logic in `NMDevice`. The main goal is to simplify `NMDevice`, so `NMDhcpClient` must become more complicated to provide a simpler (but robust) API.
+
+NMDevice has basically two timeouts (talking about IPv4, but it applies similarly to IPv6): `ipv4.dhcp-timeout` and `ipv4.required-timeout`. They control how long NMDevice is willing to try, before failing the activation altogether. Note that with `ipv4.may-fail=yes`, we may very well never want to fail the activation entirely, regardless how DHCP is doing. In that case we want to stay up, but also constantly retrying whether we cannot get a lease and recover.
+
+Currently, if `NMDhcpClient` signals a failure, then it's basically up to `NMDevice` to schedule and retry. That is complicated, and we should move the complexity out of `NMDevice`.
+
+`NMDhcpClient` should have a simpler API:
+
+- `nm_dhcp_manager_start_ip[46]()`: creates (and starts) a `NMDhcpClient` instance. The difference is, this function *never* fails to create an `NMDhcpClient`. There is no explicit `start()`, but note that the instance must not emit any signals before the next maincontext iteration (that is, it only will call back the user after a timeout or some other IO event, which happens during a future iteration of the maincontext).
+
+- `nm_dhcp_client_stop()`: when `NMDevice` is done with the `NMDhcpClient` instance, it will stop it and throw it away. This method exists because `NMDhcpClient` is a `GObject` and ref-counted. Thus, we don't want to rely on the last unref to stop the instance, but have an explicit stop. After stop, the instance is defunct and won't emit any signals anymore. There is no need to ever restart such an instance. If `NMDevice` wants to restart DHCP, it should create a new one. `NMDevice` will only want to do that, if the parameters change, hence a new instance is in order (and no need for this complexity in `NMDhcpClient`).
+
+- as already now, `NMDhcpClient` is not very configurable. You provide most (all) parameters during `nm_dhcp_manager_start_ip[46]()`, and then it keeps running until stop.
+
+- `NMDhcpClient` has a simple state:
+
+ 1. "no lease, but good". When starting, there is no lease, but we are optimistic to get one. This is the inital state, but we can also get back to this state after we had a lease (which might expire).
+
+ 1. "has a lease". Here there is no need to distinguish whether the current least was the first we received, or whether this was an update. In this state, the instance has a lease and we are very good.
+
+ 1. "no lease, but bad". `NMDhcpClient` tries really hard, and "bad" does not mean that it gave up. It will keep retrying, it's just that there is little hope of getting a new lease. This happens, when you try to run DHCP on a Layer3 link (WireGuard). There is little hope to succeed, but `NMDhcpClient` (theoretically) will retry and may recover from this. Another example is when we fail to start dhclient because it's not installed. In that case, we are not optimistic to recover, however `NMDhcpDhclient` will retry (with backoff timeout) and might still recover from this. For most cases, `NMDevice` will treat the no-lease cases the same, but in case of "bad" it might give up earlier.
+
+ When a lease expires, that does not necessarily mean that we are now in a bad state. It might mean that the DHCP server is temporarily down, but we might recover from that easily. "bad" really means, something is wrong on our side which prevents us from getting a lease. Also, imagine `dhclient` dies (we would try to restart, but assume that fails too), but we still have a valid lease, then possibly `NMDhcpClient` should still pretend all is good and we still have a lease until it expires. It may be we can recover before that happens. The point of all of this, is to hide errors as much as possibly and automatically recover. `NMDevice` will decide to tear down, if we didn't get a lease after `ipv4.dhcp-timeout`. That's the main criteria, and it might not even distinguish between "no lease, but good" and "no lease, but bad".
+
+- `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets emitted like currently, but only for the 3 simplified states. And it also provides the lease (if any).
+
+- `NMDhcpClient` will also take care of the `ipv4.dhcp-timeout` grace period. That timeout is provided during start, and starts ticking whenever there is no lease. When it expires, a timeout signal gets emitted. That's it. This is independent from the 3 states above, and only saves `NMDevice` from scheduling this timer themselves.
+
+- for nettools, `nm_dhcp_client_can_accept()` indicates that when we receive a lease, we need to accept/decline it first. In that case, `NMDevice` optionally does ACD first, then configures the IP address first and calls `nm_dhcp_client_accept()`. In case of ACD conflict, it will call `nm_dhcp_client_decline()` (which optimally causes `NMDhcpClient` to get a different lease). With this, the above state "has a lease" has actually three flavors: "has a lease but not yet ACD probed" and "has a lease but accepted/declined" (but `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets only emitted when we get the lease, not when we accept/decline it). With `dhclient`, when we receive a lease, it means "has a lease but accepted" right away.
+
+- for IPv6 prefix delegation, there is also `needed_prefixes` and `NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED`. Currently `needed_prefixes` needs to be specified during start (which simplifies things). Maybe `needed_prefixes` should be changable at runtime. Otherwise, whether we have prefixes is similar to whether we have a lease, and the simple 3 states apply.
+
+
+Currently `NMDhcpManager` keeps track of the pending `NMDhcpClient` instances. I guess the idea is that it would (asynchronously) wait for the previous instance to be cleaned up before starting a new one. I don't know what that is necessary or useful. I think it can go away. At which point, `NMDhcpManager` does not do much, except providing the `GType`. Maybe most of `NMDhcpManager` can go away.
+
+When NetworkManager quits, it may want to leave the interface up. In that case, we still always want to stop the DHCP client, but possibly not deconfiguring the interface. I don't think that this concerns `NMDhcpClient`.
+
+---
+
+This work must be done on top of `th/l3cfg-$NUMBER` branch because it requires larger rework which is happening in that effort.
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index f88c79c0be..14ca1f983a 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -20,6 +20,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"
@@ -41,9 +42,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
PROP_IFACE,
PROP_IFINDEX,
PROP_MULTI_IDX,
- PROP_ROUTE_METRIC,
- PROP_ROUTE_TABLE,
- PROP_TIMEOUT,
+ PROP_NO_LEASE_TIMEOUT,
PROP_UUID,
PROP_IAID,
PROP_IAID_EXPLICIT,
@@ -54,31 +53,32 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
PROP_REJECT_SERVERS, );
typedef struct _NMDhcpClientPrivate {
- NMDedupMultiIndex * multi_idx;
- char * iface;
- GBytes * hwaddr;
- GBytes * bcast_hwaddr;
- char * uuid;
- GBytes * client_id;
- char * hostname;
- const char ** reject_servers;
- char * mud_url;
- char * anycast_address;
- GBytes * vendor_class_identifier;
- pid_t pid;
- guint timeout_id;
- guint watch_id;
- int addr_family;
- int ifindex;
- guint32 route_table;
- guint32 route_metric;
- guint32 timeout;
- guint32 iaid;
- NMDhcpState state;
- NMDhcpHostnameFlags hostname_flags;
- NMDhcpClientFlags client_flags;
- bool iaid_explicit : 1;
- bool is_stopped : 1;
+ NMDedupMultiIndex * multi_idx;
+ char * iface;
+ GBytes * hwaddr;
+ GBytes * bcast_hwaddr;
+ char * uuid;
+ GBytes * client_id;
+ char * hostname;
+ const char ** reject_servers;
+ char * mud_url;
+ char * anycast_address;
+ GBytes * vendor_class_identifier;
+ const NML3ConfigData *l3cd;
+ GSource * no_lease_timeout_source;
+ pid_t pid;
+ guint timeout_id;
+ guint watch_id;
+ int addr_family;
+ int ifindex;
+ guint no_lease_timeout;
+ guint32 iaid;
+ NMDhcpState state;
+ NMDhcpClientState client_state;
+ NMDhcpHostnameFlags hostname_flags;
+ NMDhcpClientFlags client_flags;
+ bool iaid_explicit : 1;
+ bool is_stopped : 1;
} NMDhcpClientPrivate;
G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT)
@@ -98,25 +98,6 @@ _emit_notify(NMDhcpClient *self, const NMDhcpClientNotifyData *notify_data)
g_signal_emit(G_OBJECT(self), signals[SIGNAL_NOTIFY], 0, notify_data);
}
-static void
-_emit_notify_state_changed(NMDhcpClient *self,
- NMDhcpState dhcp_state,
- NMIPConfig * ip_config,
- GHashTable * options)
-{
- const NMDhcpClientNotifyData notify_data = {
- .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
- .state_changed =
- {
- .dhcp_state = dhcp_state,
- .ip_config = ip_config,
- .options = options,
- },
- };
-
- _emit_notify(self, &notify_data);
-}
-
/*****************************************************************************/
pid_t
@@ -184,52 +165,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);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->timeout;
-}
-
-guint32
nm_dhcp_client_get_iaid(NMDhcpClient *self)
{
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
@@ -369,6 +304,16 @@ nm_dhcp_client_get_reject_servers(NMDhcpClient *self)
/*****************************************************************************/
+NM_UTILS_LOOKUP_STR_DEFINE(
+ nm_dhcp_client_state_to_string,
+ NMDhcpClientState,
+ NM_UTILS_LOOKUP_DEFAULT(NULL),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_CLIENT_STATE_NO_LEASE, "no-lease"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT, "no-lease-timeout"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT, "with-lease-init"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED, "with-lease-accepted"),
+ NM_UTILS_LOOKUP_STR_ITEM(NM_DHCP_CLIENT_STATE_WITH_LEASE_DECLINED, "with-lease-declined"), );
+
NM_UTILS_LOOKUP_STR_DEFINE(nm_dhcp_state_to_string,
NMDhcpState,
NM_UTILS_LOOKUP_DEFAULT(NULL),
@@ -462,73 +407,146 @@ stop(NMDhcpClient *self, gboolean release)
priv->pid = -1;
}
-void
-nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options)
+static gboolean
+_no_lease_timeout(gpointer user_data)
{
+ NMDhcpClient * self = user_data;
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+
+ nm_assert(priv->client_state == NM_DHCP_CLIENT_STATE_NO_LEASE);
+ priv->client_state = NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT;
+
+ _emit_notify(self,
+ &((NMDhcpClientNotifyData){
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+ }));
+ return G_SOURCE_CONTINUE;
+}
+
+void
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3ConfigData *l3cd)
+{
+ NMDhcpClientPrivate * priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ GHashTable * options;
+ const int IS_IPv4 = NM_IS_IPv4(priv->addr_family);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_merged = NULL;
+ NMDhcpClientState new_client_state;
+
+ 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);
if (new_state >= NM_DHCP_STATE_TIMEOUT)
watch_cleanup(self);
- /* The client may send same-state transitions for RENEW/REBIND events and
- * the lease may have changed, so handle same-state transitions for the
- * EXTENDED and BOUND states. Ignore same-state transitions for other
- * events since the lease won't have changed and the state was already handled.
- */
- if ((priv->state == new_state)
- && !NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED))
- return;
+ if (!IS_IPv4 && l3cd) {
+ if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cd, l3cd, &l3cd_merged)) {
+ l3cd = nm_l3_config_data_seal(l3cd_merged);
+ }
+ }
- 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;
+
+ if (!l3cd) {
+ new_client_state = (priv->client_state == NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT)
+ ? NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT
+ : NM_DHCP_CLIENT_STATE_NO_LEASE;
+ } else {
+ new_client_state = nm_dhcp_client_can_accept(self)
+ ? NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT
+ : NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED;
+ }
+
+ /* FIXME(simple-dhcp): the API of NMDhcpClient is changing to expose a simpler API.
+ * The internals like NMDhcpState should not be exposed (or possibly dropped in large
+ * parts). */
+
+ if (priv->client_state == new_client_state && priv->l3cd == l3cd)
+ return;
- keys = nm_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 (l3cd)
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+ else {
+ if (!priv->no_lease_timeout_source
+ && priv->client_state != NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT) {
+ if (priv->no_lease_timeout == NM_DHCP_TIMEOUT_INFINITY)
+ priv->no_lease_timeout_source = g_source_ref(nm_g_source_sentinel_get(0));
+ else {
+ priv->no_lease_timeout_source =
+ nm_g_timeout_add_source_seconds(priv->no_lease_timeout,
+ _no_lease_timeout,
+ self);
+ }
}
}
- if (_LOGT_ENABLED() && priv->addr_family == AF_INET6) {
- gs_free char *event_id = NULL;
+ priv->client_state = new_client_state;
+ nm_l3_config_data_reset(&priv->l3cd, l3cd);
+
+ if (_LOGD_ENABLED()) {
+ if (options) {
+ gs_free const char **keys = NULL;
+ guint nkeys;
+ guint i;
+
+ keys = nm_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 (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()) {
const char *req_str =
- NM_IS_IPv4(priv->addr_family)
- ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
- : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
+ IS_IPv4 ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
+ : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
const char *addr = nm_g_hash_table_lookup(options, req_str);
- _LOGI("state changed %s -> %s%s%s%s",
- nm_dhcp_state_to_string(priv->state),
- nm_dhcp_state_to_string(new_state),
+ _LOGI("state changed %s%s%s%s",
+ nm_dhcp_client_state_to_string(priv->client_state),
NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", ""));
}
- priv->state = new_state;
-
- _emit_notify_state_changed(self, new_state, ip_config, options);
+ {
+ const NMDhcpClientNotifyData notify_data = {
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+ .lease_update =
+ {
+ .dhcp_state = priv->client_state,
+ .l3cd = priv->l3cd,
+ },
+ };
+
+ _emit_notify(self, &notify_data);
+ }
}
-static gboolean
+/* FIXME(simple-dhcp) */
+_nm_unused static gboolean
transaction_timeout(gpointer user_data)
{
NMDhcpClient * self = NM_DHCP_CLIENT(user_data);
@@ -536,7 +554,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;
}
@@ -554,7 +572,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
@@ -566,10 +584,10 @@ nm_dhcp_client_start_timeout(NMDhcpClient *self)
/* Set up a timeout on the transaction to kill it after the timeout */
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
- return;
-
- priv->timeout_id = g_timeout_add_seconds(priv->timeout, transaction_timeout, self);
+ /* FIXME(simple-dhcp): no-lease-timeout is only for convenience for the user (NMDevice).
+ * Whatever the purpose of nm_dhcp_client_start_timeout() is, it is not the same timer. */
+ return;
+ //priv->timeout_id = g_timeout_add_seconds(priv->no_lease_timeout, transaction_timeout, self);
}
void
@@ -613,10 +631,11 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self,
g_return_val_if_fail(priv->addr_family == AF_INET, FALSE);
g_return_val_if_fail(priv->uuid != NULL, FALSE);
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ if (priv->no_lease_timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->no_lease_timeout);
nm_dhcp_client_set_client_id(self, client_id);
@@ -626,8 +645,16 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self,
gboolean
nm_dhcp_client_accept(NMDhcpClient *self, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->client_state == NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT, FALSE);
+
+ priv->client_state = NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED;
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->accept) {
return NM_DHCP_CLIENT_GET_CLASS(self)->accept(self, error);
}
@@ -652,8 +679,16 @@ nm_dhcp_client_can_accept(NMDhcpClient *self)
gboolean
nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->client_state == NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT, FALSE);
+
+ priv->client_state = NM_DHCP_CLIENT_STATE_WITH_LEASE_DECLINED;
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->decline) {
return NM_DHCP_CLIENT_GET_CLASS(self)->decline(self, error_message, error);
}
@@ -694,10 +729,11 @@ nm_dhcp_client_start_ip6(NMDhcpClient * self,
_set_client_id(self, own_client_id ?: client_id, FALSE);
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ if (priv->no_lease_timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->no_lease_timeout);
return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self,
ll_addr,
@@ -789,7 +825,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);
}
/*****************************************************************************/
@@ -921,12 +957,10 @@ 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 new_state;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address prefix = {
0,
};
@@ -943,20 +977,21 @@ nm_dhcp_client_handle_event(gpointer unused,
if (priv->pid != pid)
return FALSE;
- old_state = priv->state;
new_state = reason_to_state(self, priv->iface, reason);
+ if (new_state == NM_DHCP_STATE_NOOP)
+ return TRUE;
+
_LOGD("DHCP state '%s' -> '%s' (reason: '%s')",
- nm_dhcp_state_to_string(old_state),
+ nm_dhcp_state_to_string(priv->state),
nm_dhcp_state_to_string(new_state),
reason);
-
- if (new_state == NM_DHCP_STATE_NOOP)
- return TRUE;
+ priv->state = new_state;
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);
@@ -969,24 +1004,27 @@ 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 {
- prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
- ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options(
+ 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,
- NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)));
+ NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
}
} 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)) {
@@ -994,17 +1032,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;
}
@@ -1075,14 +1112,8 @@ 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);
+ case PROP_NO_LEASE_TIMEOUT:
+ g_value_set_uint(value, priv->no_lease_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -1163,15 +1194,9 @@ 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:
+ case PROP_NO_LEASE_TIMEOUT:
/* construct-only */
- priv->timeout = g_value_get_uint(value);
+ priv->no_lease_timeout = g_value_get_uint(value);
break;
case PROP_VENDOR_CLASS_IDENTIFIER:
/* construct-only */
@@ -1197,7 +1222,8 @@ nm_dhcp_client_init(NMDhcpClient *self)
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DHCP_CLIENT, NMDhcpClientPrivate);
self->_priv = priv;
- priv->pid = -1;
+ priv->client_state = NM_DHCP_CLIENT_STATE_NO_LEASE;
+ priv->pid = -1;
}
#if NM_MORE_ASSERTS
@@ -1243,6 +1269,7 @@ dispose(GObject *object)
nm_clear_pointer(&priv->hwaddr, g_bytes_unref);
nm_clear_pointer(&priv->bcast_hwaddr, g_bytes_unref);
nm_clear_pointer(&priv->vendor_class_identifier, g_bytes_unref);
+ nm_clear_l3cd(&priv->l3cd);
G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object);
@@ -1364,31 +1391,13 @@ 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,
+ obj_properties[PROP_NO_LEASE_TIMEOUT] =
+ g_param_spec_uint(NM_DHCP_CLIENT_NO_LEASE_TIMEOUT,
"",
"",
- 1,
- G_MAXINT32,
+ 0,
+ G_MAXUINT,
NM_DHCP_TIMEOUT_DEFAULT,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 2e7e021650..3f22eebb0e 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 */
@@ -34,9 +32,7 @@
#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_NO_LEASE_TIMEOUT "no-lease-timeout"
#define NM_DHCP_CLIENT_UUID "uuid"
#define NM_DHCP_CLIENT_IAID "iaid"
#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit"
@@ -58,8 +54,36 @@ typedef enum {
NM_DHCP_STATE_NOOP, /* state is a non operation for NetworkManager */
} NMDhcpState;
+typedef enum {
+ NM_DHCP_CLIENT_STATE_NO_LEASE,
+ NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_INIT,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_ACCEPTED,
+ NM_DHCP_CLIENT_STATE_WITH_LEASE_DECLINED,
+} NMDhcpClientState;
+
typedef enum _nm_packed {
- NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
+ NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+
+ /* When NM_DHCP_CLIENT_NO_LEASE_TIMEOUT expired and the state
+ * switched from NM_DHCP_CLIENT_STATE_NO_LEASE to
+ * NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+
+ /* NMDhcpClient will indefinitely try to get/renew the lease.
+ * As such, it's never officially in a non-recoverable state.
+ * However, there are cases when it really looks like we won't
+ * be able to get a lease. For example, if the underlying interface
+ * is layer 3 only, if we have no IPv6 link local address for a prolonged
+ * time, or if dhclient is not installed.
+ * But even these cases are potentially recoverable. This is only
+ * a hint to the user (which they might ignore).
+ *
+ * In particular, NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT might mean
+ * that the DHCP is currently not running, but that could change
+ * at any moment and from client's side, it does not look bad. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD,
+
NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED,
} NMDhcpClientNotifyType;
@@ -67,16 +91,25 @@ typedef struct {
NMDhcpClientNotifyType notify_type;
union {
struct {
- NMIPConfig *ip_config;
- GHashTable *options;
- NMDhcpState dhcp_state;
- } state_changed;
+ /* this is either the new lease information we just received,
+ * or NULL (if a previous lease timed out).
+ *
+ * If nm_dhcp_client_can_accept(), then the user first has to
+ * ACD the address (optionally), configure it and accept/decline
+ * it.
+ * If !nm_dhcp_client_can_accept(), then the lease is already
+ * accepted. */
+ const NML3ConfigData *l3cd;
+
+ NMDhcpClientState dhcp_state;
+ } lease_update;
struct {
const NMPlatformIP6Address *prefix;
} prefix_delegated;
};
} NMDhcpClientNotifyData;
+const char *nm_dhcp_client_state_to_string(NMDhcpClientState state);
const char *nm_dhcp_state_to_string(NMDhcpState state);
struct _NMDhcpClientPrivate;
@@ -148,16 +181,6 @@ GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self);
const char *nm_dhcp_client_get_anycast_address(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);
gboolean nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self);
@@ -205,10 +228,8 @@ 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, const 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 3ea481c385..8353f5e04d 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-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 970a51f5dd..0540702c96 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -530,7 +530,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
client_id,
nm_dhcp_client_get_anycast_address(client),
nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
+ NM_DHCP_TIMEOUT_INFINITY, /* FIXME(simple-dhcp) */
NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN),
nm_dhcp_client_get_hostname_flags(client),
nm_dhcp_client_get_mud_url(client),
@@ -570,7 +570,7 @@ ip6_start(NMDhcpClient * client,
NULL,
nm_dhcp_client_get_anycast_address(client),
nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
+ NM_DHCP_TIMEOUT_INFINITY, /* FIXME(simple-dhcp) */
TRUE,
nm_dhcp_client_get_hostname_flags(client),
nm_dhcp_client_get_mud_url(client),
diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c
index 3cb893932d..8f80c2a997 100644
--- a/src/core/dhcp/nm-dhcp-manager.c
+++ b/src/core/dhcp/nm-dhcp-manager.c
@@ -138,8 +138,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,
@@ -242,11 +240,7 @@ 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,
+ NM_DHCP_CLIENT_NO_LEASE_TIMEOUT,
(guint) timeout,
NM_DHCP_CLIENT_HOSTNAME_FLAGS,
(guint) hostname_flags,
@@ -313,8 +307,6 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self,
GBytes * hwaddr,
GBytes * bcast_hwaddr,
const char * uuid,
- guint32 route_table,
- guint32 route_metric,
NMDhcpClientFlags client_flags,
gboolean send_hostname,
const char * dhcp_hostname,
@@ -374,8 +366,6 @@ nm_dhcp_manager_start_ip4(NMDhcpManager * self,
hwaddr,
bcast_hwaddr,
uuid,
- route_table,
- route_metric,
NULL,
dhcp_client_id,
FALSE,
@@ -403,8 +393,6 @@ nm_dhcp_manager_start_ip6(NMDhcpManager * self,
int ifindex,
const struct in6_addr * ll_addr,
const char * uuid,
- guint32 route_table,
- guint32 route_metric,
NMDhcpClientFlags client_flags,
gboolean send_hostname,
const char * dhcp_hostname,
@@ -441,8 +429,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 ce160437a5..ab44158cee 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,8 +38,6 @@ NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager,
GBytes * hwaddr,
GBytes * bcast_hwaddr,
const char * uuid,
- guint32 route_table,
- guint32 route_metric,
NMDhcpClientFlags client_flags,
gboolean send_hostname,
const char * dhcp_hostname,
@@ -61,8 +58,6 @@ NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager,
int ifindex,
const struct in6_addr * ll_addr,
const char * uuid,
- guint32 route_table,
- guint32 route_metric,
NMDhcpClientFlags client_flags,
gboolean send_hostname,
const char * dhcp_hostname,
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index 56b485dd25..71221acca6 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;
@@ -367,26 +366,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,
+ }));
}
has_classless = TRUE;
@@ -419,17 +414,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,
@@ -463,19 +458,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,
@@ -486,7 +479,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;
@@ -504,7 +497,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,
@@ -539,34 +532,31 @@ 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_IP_CONFIG_SOURCE_DHCP);
- if (!lease_parse_address(lease, ip4_config, options, error))
+ options = nm_dhcp_option_create_options_dict();
+
+ if (!lease_parse_address(lease, l3cd, options, error))
return NULL;
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
@@ -585,13 +575,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)) {
@@ -616,7 +602,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);
}
}
@@ -628,18 +614,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) {
@@ -650,7 +635,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)) {
@@ -681,11 +666,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* We reject NUL characters inside the string (except trailing NULs).
* Otherwise, we allow any encoding and backslash-escape the result to
* UTF-8. */
- nm_dhcp_option_add_option_utf8safe_escape(options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped = 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_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len);
@@ -700,7 +691,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
&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 ?: "");
}
r = n_dhcp4_client_lease_get_file(lease, &v_str);
@@ -728,18 +719,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
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);
}
/*****************************************************************************/
@@ -771,36 +761,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
@@ -835,10 +819,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);
@@ -890,13 +874,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;
}
@@ -1033,7 +1016,7 @@ decline(NMDhcpClient *client, const char *error_message, GError **error)
g_return_val_if_fail(priv->lease, FALSE);
- _LOGT("dhcp4-client: decline");
+ _LOGT("dhcp4-client: decline (%s)", error_message);
r = n_dhcp4_client_lease_decline(priv->lease, error_message);
if (r) {
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index af1d2238b4..1e6a2b4140 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,9 @@ 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, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ 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 +157,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 +190,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 +203,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 +221,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 +230,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 +304,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 +336,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 +362,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 +414,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) {
@@ -436,12 +429,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
- nm_dhcp_option_add_option_utf8safe_escape(
- options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped =
+ 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_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
continue;
}
@@ -458,8 +457,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_take_option(options, AF_INET, 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);
}
/*****************************************************************************/
@@ -467,43 +470,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
@@ -522,10 +520,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:
@@ -759,32 +757,32 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
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, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ options = nm_dhcp_option_create_options_dict();
sd_dhcp6_lease_reset_address_iter(lease);
nm_gstring_prepare(&str);
@@ -798,15 +796,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,
@@ -820,7 +822,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);
}
@@ -830,7 +832,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);
}
@@ -839,51 +841,46 @@ 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");
- 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_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
- &options,
- ts,
- &error);
-
- if (!ip6_config) {
+ 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_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
+ NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
+ ts,
+ &error);
+
+ 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,
@@ -908,11 +905,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 3cc6987ada..22a03701b1 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,43 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
searches = nm_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_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 +422,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));
@@ -453,7 +437,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
gs_free const char **routers = nm_strsplit_set(str, " ");
const 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);
@@ -469,11 +453,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 +469,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 +484,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 +499,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 +515,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 +533,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 +550,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 +559,20 @@ 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);
+ str = g_hash_table_lookup(options, "wpad");
+ if (str) {
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, str);
+ }
+
+ 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 +623,29 @@ 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();
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ .timestamp = now,
+ };
+
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
str = g_hash_table_lookup(options, "max_life");
if (str) {
@@ -676,7 +668,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 +687,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 +697,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 +830,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);
+
+ /* FIXME: Note that we keep the original NMDhcpLease. All we take from the new lease are the
+ * addresses. Maybe this is not right and we should merge the leases too?? */
+ 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/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c
index 126e0a217a..b40521a32b 100644
--- a/src/core/dns/nm-dns-dnsmasq.c
+++ b/src/core/dns/nm-dns-dnsmasq.c
@@ -19,10 +19,9 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-platform/nm-platform.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dbus-manager.h"
#include "NetworkManagerUtils.h"
+#include "nm-l3-config-data.h"
#define PIDFILE NMRUNDIR "/dnsmasq.pid"
#define CONFDIR NMCONFDIR "/dnsmasq.d"
@@ -806,20 +805,22 @@ add_global_config(NMDnsDnsmasq * self,
static void
add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data)
{
- NMIPConfig * ip_config = ip_data->ip_config;
- gconstpointer addr;
- const char * iface, *domain;
+ const char * iface;
+ const char * domain;
char ip_addr_to_string_buf[IP_ADDR_TO_STRING_BUFLEN];
- int addr_family;
- guint i, j, num;
+ gconstpointer nameservers;
+ guint num;
+ guint i;
+ guint j;
- iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
- addr_family = nm_ip_config_get_addr_family(ip_config);
+ iface = nm_platform_link_get_name(NM_PLATFORM_GET, ip_data->data->ifindex);
- num = nm_ip_config_get_num_nameservers(ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
for (i = 0; i < num; i++) {
- addr = nm_ip_config_get_nameserver(ip_config, i);
- ip_addr_to_string(addr_family, addr, iface, ip_addr_to_string_buf);
+ gconstpointer addr;
+
+ addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i);
+ ip_addr_to_string(ip_data->addr_family, addr, iface, ip_addr_to_string_buf);
if (!ip_data->domains.has_default_route_explicit && ip_data->domains.has_default_route)
add_dnsmasq_nameserver(self, servers, ip_addr_to_string_buf, NULL);
@@ -846,7 +847,7 @@ add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPD
static GVariant *
create_update_args(NMDnsDnsmasq * self,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname)
{
GVariantBuilder servers;
@@ -857,7 +858,7 @@ create_update_args(NMDnsDnsmasq * self,
if (global_config)
add_global_config(self, &servers, global_config);
else {
- c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst)
+ c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst)
add_ip_config(self, &servers, ip_data);
}
@@ -1122,7 +1123,7 @@ start_dnsmasq(NMDnsDnsmasq *self, gboolean force_start, GError **error)
static gboolean
update(NMDnsPlugin * plugin,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname,
GError ** error)
{
@@ -1134,7 +1135,7 @@ update(NMDnsPlugin * plugin,
nm_clear_pointer(&priv->set_server_ex_args, g_variant_unref);
priv->set_server_ex_args =
- g_variant_ref_sink(create_update_args(self, global_config, ip_config_lst_head, hostname));
+ g_variant_ref_sink(create_update_args(self, global_config, ip_data_lst_head, hostname));
send_dnsmasq_update(self);
return TRUE;
diff --git a/src/core/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c
index f0ec0c8921..d4491d30ae 100644
--- a/src/core/dns/nm-dns-manager.c
+++ b/src/core/dns/nm-dns-manager.c
@@ -7,6 +7,8 @@
#include "src/core/nm-default-daemon.h"
+#include "nm-dns-manager.h"
+
#include <fcntl.h>
#include <resolv.h>
#include <stdlib.h>
@@ -22,22 +24,20 @@
#include <libpsl.h>
#endif
-#include "libnm-glib-aux/nm-str-buf.h"
-#include "nm-utils.h"
#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-dns-manager.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "libnm-glib-aux/nm-str-buf.h"
+
#include "NetworkManagerUtils.h"
+#include "devices/nm-device.h"
#include "nm-config.h"
#include "nm-dbus-object.h"
-#include "devices/nm-device.h"
-#include "nm-manager.h"
-
-#include "nm-dns-plugin.h"
#include "nm-dns-dnsmasq.h"
+#include "nm-dns-plugin.h"
#include "nm-dns-systemd-resolved.h"
#include "nm-dns-unbound.h"
+#include "nm-l3-config-data.h"
+#include "nm-manager.h"
+#include "nm-utils.h"
#define HASH_LEN NM_UTILS_CHECKSUM_LENGTH_SHA1
@@ -84,10 +84,10 @@ typedef struct {
GHashTable *configs_dict;
CList configs_lst_head;
- CList ip_config_lst_head;
+ CList ip_data_lst_head;
GVariant *config_variant;
- bool ip_config_lst_need_sort : 1;
+ bool ip_data_lst_need_sort : 1;
bool configs_lst_need_sort : 1;
@@ -159,11 +159,6 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER
/*****************************************************************************/
-static void
-_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data);
-
-/*****************************************************************************/
-
static gboolean
domain_is_valid(const char *domain, gboolean check_public_suffix)
{
@@ -208,6 +203,24 @@ static NM_UTILS_LOOKUP_STR_DEFINE(
/*****************************************************************************/
+static int
+_dns_config_ip_data_get_dns_priority1(const NML3ConfigData *l3cd, int addr_family)
+{
+ int prio;
+
+ if (!nm_l3_config_data_get_dns_priority(l3cd, addr_family, &prio))
+ return 0;
+
+ nm_assert(prio != 0);
+ return prio;
+}
+
+static int
+_dns_config_ip_data_get_dns_priority(const NMDnsConfigIPData *ip_data)
+{
+ return _dns_config_ip_data_get_dns_priority1(ip_data->l3cd, ip_data->addr_family);
+}
+
static void
_ASSERT_dns_config_data(const NMDnsConfigData *data)
{
@@ -221,9 +234,9 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data)
{
nm_assert(ip_data);
_ASSERT_dns_config_data(ip_data->data);
- nm_assert(NM_IS_IP_CONFIG(ip_data->ip_config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(ip_data->l3cd));
nm_assert(c_list_contains(&ip_data->data->data_lst_head, &ip_data->data_lst));
- nm_assert(ip_data->data->ifindex == nm_ip_config_get_ifindex(ip_data->ip_config));
+ nm_assert(ip_data->data->ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd));
#if NM_MORE_ASSERTS > 5
{
gboolean has_default = FALSE;
@@ -243,37 +256,36 @@ _ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data)
if (ip_data->domains.has_default_route_exclusive)
nm_assert(ip_data->domains.has_default_route);
}
+ nm_assert(_dns_config_ip_data_get_dns_priority(ip_data) != 0);
#endif
}
static NMDnsConfigIPData *
-_dns_config_ip_data_new(NMDnsConfigData * data,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type)
+_dns_config_ip_data_new(NMDnsConfigData * data,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type)
{
NMDnsConfigIPData *ip_data;
_ASSERT_dns_config_data(data);
- nm_assert(NM_IS_IP_CONFIG(ip_config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
ip_data = g_slice_new(NMDnsConfigIPData);
*ip_data = (NMDnsConfigIPData){
.data = data,
- .ip_config = g_object_ref(ip_config),
+ .source_tag = source_tag,
+ .l3cd = nm_l3_config_data_ref_and_seal(l3cd),
.ip_config_type = ip_config_type,
+ .addr_family = addr_family,
};
c_list_link_tail(&data->data_lst_head, &ip_data->data_lst);
- c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_config_lst_head,
- &ip_data->ip_config_lst);
-
- /* We also need to set priv->ip_config_lst_need_sort, but the caller will do that! */
+ c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_data_lst_head,
+ &ip_data->ip_data_lst);
- g_signal_connect(ip_config,
- NM_IS_IP4_CONFIG(ip_config) ? "notify::" NM_IP4_CONFIG_DNS_PRIORITY
- : "notify::" NM_IP6_CONFIG_DNS_PRIORITY,
- G_CALLBACK(_ip_config_dns_priority_changed),
- ip_data);
+ /* We also need to set priv->ip_data_lst_need_sort, but the caller will do that! */
_ASSERT_dns_config_ip_data(ip_data);
return ip_data;
@@ -285,35 +297,15 @@ _dns_config_ip_data_free(NMDnsConfigIPData *ip_data)
_ASSERT_dns_config_ip_data(ip_data);
c_list_unlink_stale(&ip_data->data_lst);
- c_list_unlink_stale(&ip_data->ip_config_lst);
+ c_list_unlink_stale(&ip_data->ip_data_lst);
g_free(ip_data->domains.search);
g_strfreev(ip_data->domains.reverse);
- g_signal_handlers_disconnect_by_func(ip_data->ip_config,
- _ip_config_dns_priority_changed,
- ip_data);
-
- g_object_unref(ip_data->ip_config);
+ nm_l3_config_data_unref(ip_data->l3cd);
nm_g_slice_free(ip_data);
}
-static NMDnsConfigIPData *
-_dns_config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config)
-{
- NMDnsConfigIPData *ip_data;
-
- _ASSERT_dns_config_data(data);
-
- c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) {
- _ASSERT_dns_config_ip_data(ip_data);
-
- if (ip_data->ip_config == ip_config)
- return ip_data;
- }
- return NULL;
-}
-
static void
_dns_config_data_free(NMDnsConfigData *data)
{
@@ -325,14 +317,13 @@ _dns_config_data_free(NMDnsConfigData *data)
}
static int
-_mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data)
+_mgr_get_ip_data_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data)
{
- const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_config_lst);
- const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_config_lst);
+ const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_data_lst);
+ const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_data_lst);
/* Configurations with lower priority value first */
- NM_CMP_DIRECT(nm_ip_config_get_dns_priority(a->ip_config),
- nm_ip_config_get_dns_priority(b->ip_config));
+ NM_CMP_DIRECT(_dns_config_ip_data_get_dns_priority(a), _dns_config_ip_data_get_dns_priority(b));
/* Sort according to type (descendingly) */
NM_CMP_FIELD(b, a, ip_config_type);
@@ -341,16 +332,16 @@ _mgr_get_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *u
}
static CList *
-_mgr_get_ip_config_lst_head(NMDnsManager *self)
+_mgr_get_ip_data_lst_head(NMDnsManager *self)
{
NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self);
- if (G_UNLIKELY(priv->ip_config_lst_need_sort)) {
- priv->ip_config_lst_need_sort = FALSE;
- c_list_sort(&priv->ip_config_lst_head, _mgr_get_ip_config_lst_cmp, NULL);
+ if (G_UNLIKELY(priv->ip_data_lst_need_sort)) {
+ priv->ip_data_lst_need_sort = FALSE;
+ c_list_sort(&priv->ip_data_lst_head, _mgr_get_ip_data_lst_cmp, NULL);
}
- return &priv->ip_config_lst_head;
+ return &priv->ip_data_lst_head;
}
static int
@@ -430,28 +421,33 @@ add_dns_option_item(GPtrArray *array, const char *str)
}
static void
-add_dns_domains(GPtrArray * array,
- const NMIPConfig *ip_config,
- gboolean include_routing,
- gboolean dup)
+add_dns_domains(GPtrArray * array,
+ int addr_family,
+ const NML3ConfigData *l3cd,
+ gboolean include_routing,
+ gboolean dup)
{
- guint num_domains, num_searches, i;
- const char *str;
+ const char *const *domains;
+ const char *const *searches;
+ guint num_domains;
+ guint num_searches;
+ guint i;
+ const char * str;
- num_domains = nm_ip_config_get_num_domains(ip_config);
- num_searches = nm_ip_config_get_num_searches(ip_config);
+ domains = nm_l3_config_data_get_domains(l3cd, addr_family, &num_domains);
+ searches = nm_l3_config_data_get_searches(l3cd, addr_family, &num_searches);
for (i = 0; i < num_searches; i++) {
- str = nm_ip_config_get_search(ip_config, i);
+ str = searches[i];
if (!include_routing && domain_is_routing(str))
continue;
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
continue;
add_string_item(array, str, dup);
}
- if (num_domains > 1 || !num_searches) {
+ if (num_domains > 1 || num_searches == 0) {
for (i = 0; i < num_domains; i++) {
- str = nm_ip_config_get_domain(ip_config, i);
+ str = domains[i];
if (!include_routing && domain_is_routing(str))
continue;
if (!domain_is_valid(nm_utils_parse_dns_domain(str, NULL), FALSE))
@@ -462,26 +458,24 @@ add_dns_domains(GPtrArray * array,
}
static void
-merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_config)
+merge_one_l3cd(NMResolvConfData *rc, int addr_family, int ifindex, const NML3ConfigData *l3cd)
{
- int addr_family;
- char buf[NM_UTILS_INET_ADDRSTRLEN + 50];
- gboolean has_trust_ad;
- guint num_nameservers;
- guint num;
- guint i;
-
- addr_family = nm_ip_config_get_addr_family(ip_config);
+ char buf[NM_UTILS_INET_ADDRSTRLEN + 50];
+ gboolean has_trust_ad;
+ guint num_nameservers;
+ guint num;
+ guint i;
+ gconstpointer nameservers;
+ const char *const *strv;
- nm_assert_addr_family(addr_family);
- nm_assert(ifindex > 0);
- nm_assert(ifindex == nm_ip_config_get_ifindex(ip_config));
+ nm_assert(ifindex == nm_l3_config_data_get_ifindex(l3cd));
- num_nameservers = nm_ip_config_get_num_nameservers(ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num_nameservers);
for (i = 0; i < num_nameservers; i++) {
const NMIPAddr *addr;
- addr = nm_ip_config_get_nameserver(ip_config, i);
+ addr = nm_ip_addr_from_packed_array(addr_family, nameservers, i);
+
if (addr_family == AF_INET)
nm_utils_inet_ntop(addr_family, addr, buf);
else if (IN6_IS_ADDR_V4MAPPED(addr))
@@ -502,22 +496,23 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf
add_string_item(rc->nameservers, buf, TRUE);
}
- add_dns_domains(rc->searches, ip_config, FALSE, TRUE);
+ add_dns_domains(rc->searches, addr_family, l3cd, FALSE, TRUE);
has_trust_ad = FALSE;
- num = nm_ip_config_get_num_dns_options(ip_config);
+ strv = nm_l3_config_data_get_dns_options(l3cd, addr_family, &num);
for (i = 0; i < num; i++) {
- const char *option = nm_ip_config_get_dns_option(ip_config, i);
+ const char *option = strv[i];
if (nm_streq(option, NM_SETTING_DNS_OPTION_TRUST_AD)) {
has_trust_ad = TRUE;
continue;
}
- add_dns_option_item(rc->options, nm_ip_config_get_dns_option(ip_config, i));
+ add_dns_option_item(rc->options, option);
}
+
if (num_nameservers == 0) {
- /* If the @ip_config contributes no DNS servers, ignore whether trust-ad is set or unset
- * for this @ip_config. */
+ /* If the @l3cd contributes no DNS servers, ignore whether trust-ad is set or unset
+ * for this @l3cd. */
} else if (has_trust_ad) {
/* We only set has_trust_ad to TRUE, if all IP configs agree (or don't contribute).
* Once set to FALSE, it doesn't get reset. */
@@ -527,20 +522,17 @@ merge_one_ip_config(NMResolvConfData *rc, int ifindex, const NMIPConfig *ip_conf
rc->has_trust_ad = NM_TERNARY_FALSE;
if (addr_family == AF_INET) {
- const NMIP4Config *ip4_config = (const NMIP4Config *) ip_config;
+ const in_addr_t *nis_servers;
+ const char * nis_domain;
- /* NIS stuff */
- num = nm_ip4_config_get_num_nis_servers(ip4_config);
- for (i = 0; i < num; i++) {
- add_string_item(rc->nis_servers,
- _nm_utils_inet4_ntop(nm_ip4_config_get_nis_server(ip4_config, i), buf),
- TRUE);
- }
+ nis_servers = nm_l3_config_data_get_nis_servers(l3cd, &num);
+ for (i = 0; i < num; i++)
+ add_string_item(rc->nis_servers, _nm_utils_inet4_ntop(nis_servers[i], buf), TRUE);
- if (nm_ip4_config_get_nis_domain(ip4_config)) {
+ if ((nis_domain = nm_l3_config_data_get_nis_domain(l3cd))) {
/* FIXME: handle multiple domains */
if (!rc->nis_domain)
- rc->nis_domain = nm_ip4_config_get_nis_domain(ip4_config);
+ rc->nis_domain = nis_domain;
}
}
}
@@ -1122,9 +1114,9 @@ compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[
/* FIXME(ip-config-checksum): this relies on the fact that an IP
* configuration without DNS parameters gives a zero checksum. */
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst)
- nm_ip_config_hash(ip_data->ip_config, sum, TRUE);
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst)
+ ; //XXX nm_ip_config_hash(ip_data->l3cd, sum, TRUE);
}
nm_utils_checksum_get_digest_len(sum, buffer, HASH_LEN);
@@ -1172,19 +1164,18 @@ merge_global_dns_config(NMResolvConfData *rc, NMGlobalDnsConfig *global_conf)
}
static const char *
-get_nameserver_list(const NMIPConfig *config, NMStrBuf *tmp_strbuf)
+get_nameserver_list(int addr_family, const NML3ConfigData *l3cd, NMStrBuf *tmp_strbuf)
{
- char buf[NM_UTILS_INET_ADDRSTRLEN];
- int addr_family;
- guint num;
- guint i;
+ char buf[NM_UTILS_INET_ADDRSTRLEN];
+ const char *const *strv;
+ guint num;
+ guint i;
nm_str_buf_reset(tmp_strbuf);
- addr_family = nm_ip_config_get_addr_family(config);
- num = nm_ip_config_get_num_nameservers(config);
+ strv = nm_l3_config_data_get_nameservers(l3cd, addr_family, &num);
for (i = 0; i < num; i++) {
- nm_utils_inet_ntop(addr_family, nm_ip_config_get_nameserver(config, i), buf);
+ nm_utils_inet_ntop(addr_family, strv[i], buf);
if (i > 0)
nm_str_buf_append_c(tmp_strbuf, ' ');
nm_str_buf_append(tmp_strbuf, buf);
@@ -1227,36 +1218,39 @@ _collect_resolv_conf_data(NMDnsManager * self,
merge_global_dns_config(&rc, global_config);
else {
nm_auto_str_buf NMStrBuf tmp_strbuf = NM_STR_BUF_INIT(0, FALSE);
- int prio;
int first_prio = 0;
const NMDnsConfigIPData *ip_data;
const CList * head;
gboolean is_first = TRUE;
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
gboolean skip = FALSE;
+ int dns_priority;
_ASSERT_dns_config_ip_data(ip_data);
- prio = nm_ip_config_get_dns_priority(ip_data->ip_config);
+ if (!nm_l3_config_data_get_dns_priority(ip_data->l3cd,
+ ip_data->addr_family,
+ &dns_priority))
+ nm_assert_not_reached();
if (is_first) {
is_first = FALSE;
- first_prio = prio;
- } else if (first_prio < 0 && first_prio != prio)
+ first_prio = dns_priority;
+ } else if (first_prio < 0 && first_prio != dns_priority)
skip = TRUE;
_LOGT("config: %8d %-7s v%c %-5d %s: %s",
- prio,
+ dns_priority,
_config_type_to_string(ip_data->ip_config_type),
- nm_utils_addr_family_to_char(nm_ip_config_get_addr_family(ip_data->ip_config)),
+ nm_utils_addr_family_to_char(ip_data->addr_family),
ip_data->data->ifindex,
skip ? "<SKIP>" : "",
- get_nameserver_list(ip_data->ip_config, &tmp_strbuf));
+ get_nameserver_list(ip_data->addr_family, ip_data->l3cd, &tmp_strbuf));
if (!skip)
- merge_one_ip_config(&rc, ip_data->data->ifindex, ip_data->ip_config);
+ merge_one_l3cd(&rc, ip_data->addr_family, ip_data->data->ifindex, ip_data->l3cd);
}
}
@@ -1292,27 +1286,32 @@ _collect_resolv_conf_data(NMDnsManager * self,
/*****************************************************************************/
static char **
-get_ip_rdns_domains(NMIPConfig *ip_config)
+get_ip_rdns_domains(int addr_family, const NML3ConfigData *l3cd)
{
- int addr_family = nm_ip_config_get_addr_family(ip_config);
- char ** strv;
- GPtrArray * domains;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIPAddress *address;
- const NMPlatformIPRoute * route;
-
- nm_assert_addr_family(addr_family);
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ char ** strv;
+ GPtrArray * domains;
+ NMDedupMultiIter ipconf_iter;
+ const NMPObject *obj;
domains = g_ptr_array_sized_new(5);
- nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) {
nm_utils_get_reverse_dns_domains_ip(addr_family,
- address->address_ptr,
- address->plen,
+ NMP_OBJECT_CAST_IP_ADDRESS(obj)->address_ptr,
+ NMP_OBJECT_CAST_IP_ADDRESS(obj)->plen,
domains);
}
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &route) {
+ nm_l3_config_data_iter_obj_for_each (&ipconf_iter,
+ l3cd,
+ &obj,
+ NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) {
+ const NMPlatformIPRoute *route = NMP_OBJECT_CAST_IP_ROUTE(obj);
+
if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) {
nm_utils_get_reverse_dns_domains_ip(addr_family,
route->network_ptr,
@@ -1394,12 +1393,12 @@ _mgr_configs_data_construct(NMDnsManager *self)
CList * head;
int prev_priority = G_MININT;
- head = _mgr_get_ip_config_lst_head(self);
+ head = _mgr_get_ip_data_lst_head(self);
#if NM_MORE_ASSERTS
/* we call _mgr_configs_data_clear() at the end of update. We
* don't expect any domain settings here. */
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
nm_assert(!ip_data->domains.search);
nm_assert(!ip_data->domains.reverse);
nm_assert(!ip_data->domains.has_default_route_explicit);
@@ -1408,26 +1407,28 @@ _mgr_configs_data_construct(NMDnsManager *self)
}
#endif
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- NMIPConfig *ip_config = ip_data->ip_config;
- gboolean add_wildcard = FALSE;
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ gboolean add_wildcard = FALSE;
+ guint num;
- if (!nm_ip_config_get_num_nameservers(ip_config))
+ nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
- if (nm_ip_config_best_default_route_get(ip_config))
+ if (nm_l3_config_data_get_best_default_route(ip_data->l3cd, ip_data->addr_family)) {
+ /* FIXME(l3cfg): the best-default route of a l3cd is not significant! */
add_wildcard = TRUE;
- else {
+ } else {
/* If a VPN has never-default=no but doesn't get a default
* route (this can happen for example when the server
* pushes routes with openconnect), and there are no
* search or routing domains, then the name servers pushed
* by the server would be unused. It is preferable in this
* case to use the VPN DNS server for all queries. */
- if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN
- && !nm_ip_config_get_never_default(ip_data->ip_config)
- && nm_ip_config_get_num_searches(ip_data->ip_config) == 0
- && nm_ip_config_get_num_domains(ip_data->ip_config) == 0)
- add_wildcard = TRUE;
+ //XXX if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN
+ //XXX && !nm_ip_config_get_never_default(ip_data->ip_data->l3cd)
+ //XXX && nm_ip_config_get_num_searches(ip_data->ip_data->l3cd) == 0
+ //XXX && nm_ip_config_get_num_domains(ip_data->ip_data->l3cd) == 0)
+ //XXX add_wildcard = TRUE;
}
if (add_wildcard) {
@@ -1437,29 +1438,33 @@ _mgr_configs_data_construct(NMDnsManager *self)
}
}
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- NMIPConfig * ip_config = ip_data->ip_config;
- int priority;
- const char **domains;
- guint n_searches;
- guint n_domains;
- guint num_dom1;
- guint num_dom2;
- guint n_domains_allocated;
- guint i;
- gboolean has_default_route_maybe = FALSE;
- gboolean has_default_route_explicit = FALSE;
- gboolean has_default_route_auto = FALSE;
-
- if (!nm_ip_config_get_num_nameservers(ip_config))
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ int priority;
+ const char ** domains;
+ const char *const *strv_searches;
+ const char *const *strv_domains;
+ guint n_searches;
+ guint n_domains;
+ guint num_dom1;
+ guint num_dom2;
+ guint n_domains_allocated;
+ guint i;
+ gboolean has_default_route_maybe = FALSE;
+ gboolean has_default_route_explicit = FALSE;
+ gboolean has_default_route_auto = FALSE;
+ guint num;
+
+ nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
- n_searches = nm_ip_config_get_num_searches(ip_config);
- n_domains = nm_ip_config_get_num_domains(ip_config);
+ strv_searches =
+ nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &n_searches);
+ strv_domains =
+ nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &n_domains);
- priority = nm_ip_config_get_dns_priority(ip_config);
+ priority = _dns_config_ip_data_get_dns_priority(ip_data);
- nm_assert(priority != 0);
nm_assert(prev_priority <= priority);
prev_priority = priority;
@@ -1487,10 +1492,10 @@ _mgr_configs_data_construct(NMDnsManager *self)
/* searches are preferred over domains */
if (n_searches > 0) {
for (i = 0; i < n_searches; i++)
- domains[num_dom1++] = nm_ip_config_get_search(ip_config, i);
+ domains[num_dom1++] = strv_searches[i];
} else {
for (i = 0; i < n_domains; i++)
- domains[num_dom1++] = nm_ip_config_get_domain(ip_config, i);
+ domains[num_dom1++] = strv_domains[i];
}
nm_assert(num_dom1 < n_domains_allocated);
@@ -1578,8 +1583,8 @@ _mgr_configs_data_construct(NMDnsManager *self)
nm_assert(!ip_data->domains.search);
nm_assert(!ip_data->domains.reverse);
- ip_data->domains.search = domains;
- ip_data->domains.reverse = get_ip_rdns_domains(ip_config);
+ ip_data->domains.search = domains;
+ ip_data->domains.reverse = get_ip_rdns_domains(ip_data->addr_family, ip_data->l3cd);
ip_data->domains.has_default_route_explicit = has_default_route_explicit;
ip_data->domains.has_default_route_exclusive =
has_default_route_explicit || (priority < 0 && has_default_route_auto);
@@ -1611,8 +1616,8 @@ _mgr_configs_data_clear(NMDnsManager *self)
NMDnsConfigIPData *ip_data;
CList * head;
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
nm_clear_g_free(&ip_data->domains.search);
nm_clear_pointer(&ip_data->domains.reverse, g_strfreev);
ip_data->domains.has_default_route_explicit = FALSE;
@@ -1680,7 +1685,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
if (priv->sd_resolve_plugin) {
nm_dns_plugin_update(priv->sd_resolve_plugin,
global_config,
- _mgr_get_ip_config_lst_head(self),
+ _mgr_get_ip_data_lst_head(self),
priv->hostname,
NULL);
}
@@ -1702,7 +1707,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, gboolean force_emit, GError
_LOGD("update-dns: updating plugin %s", plugin_name);
if (!nm_dns_plugin_update(plugin,
global_config,
- _mgr_get_ip_config_lst_head(self),
+ _mgr_get_ip_data_lst_head(self),
priv->hostname,
&plugin_error)) {
_LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message);
@@ -1834,53 +1839,99 @@ plugin_skip:;
/*****************************************************************************/
-static void
-_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data)
-{
- _ASSERT_dns_config_ip_data(ip_data);
-
- NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE;
-}
-
gboolean
-nm_dns_manager_set_ip_config(NMDnsManager * self,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type)
+nm_dns_manager_set_ip_config(NMDnsManager * self,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type,
+ gboolean replace_all)
{
NMDnsManagerPrivate *priv;
- NMDnsConfigIPData * ip_data;
NMDnsConfigData * data;
int ifindex;
+ gboolean changed = FALSE;
+ NMDnsConfigIPData * ip_data = NULL;
+ int dns_priority;
g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE);
- g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE);
+ g_return_val_if_fail(NM_IS_L3_CONFIG_DATA(l3cd), FALSE);
+ g_return_val_if_fail(source_tag, FALSE);
+
+ ifindex = nm_l3_config_data_get_ifindex(l3cd);
+ nm_assert(ifindex > 0);
- ifindex = nm_ip_config_get_ifindex(ip_config);
- g_return_val_if_fail(ifindex > 0, FALSE);
+ if (addr_family == AF_UNSPEC) {
+ /* Setting AF_UNSPEC is a shortcut for calling this function twice for AF_INET and
+ * AF_INET6. */
+ if (nm_dns_manager_set_ip_config(self,
+ AF_INET,
+ source_tag,
+ l3cd,
+ ip_config_type,
+ replace_all))
+ changed = TRUE;
+ if (nm_dns_manager_set_ip_config(self,
+ AF_INET6,
+ source_tag,
+ l3cd,
+ ip_config_type,
+ replace_all))
+ changed = TRUE;
+ return changed;
+ }
+
+ nm_assert_addr_family(addr_family);
priv = NM_DNS_MANAGER_GET_PRIVATE(self);
data = g_hash_table_lookup(priv->configs_dict, &ifindex);
- if (!data)
- ip_data = NULL;
- else
- ip_data = _dns_config_data_find_ip_config(data, ip_config);
- if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) {
- if (!ip_data)
- return FALSE;
- /* deleting a config doesn't invalidate the configs' sort order. */
- _dns_config_ip_data_free(ip_data);
- if (c_list_is_empty(&data->data_lst_head))
- g_hash_table_remove(priv->configs_dict, &ifindex);
- goto changed;
+ if (data) {
+ NMDnsConfigIPData *ip_data_iter;
+ NMDnsConfigIPData *ip_data_safe;
+
+ c_list_for_each_entry_safe (ip_data_iter, ip_data_safe, &data->data_lst_head, data_lst) {
+ _ASSERT_dns_config_ip_data(ip_data_iter);
+
+ if (ip_data_iter->source_tag != source_tag)
+ continue;
+ if (ip_data_iter->addr_family != addr_family)
+ continue;
+
+ if (ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED && ip_data_iter->l3cd == l3cd) {
+ nm_assert(!ip_data);
+ ip_data = ip_data_iter;
+ continue;
+ }
+
+ if (!replace_all && l3cd && ip_data_iter->l3cd != l3cd)
+ continue;
+
+ changed = TRUE;
+ _dns_config_ip_data_free(ip_data_iter);
+ }
}
+ if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED)
+ goto done;
+
+ if (!l3cd)
+ goto done;
+
if (ip_data && ip_data->ip_config_type == ip_config_type) {
/* nothing to do. */
- return FALSE;
+ goto done;
+ }
+
+ dns_priority = _dns_config_ip_data_get_dns_priority1(l3cd, addr_family);
+ if (dns_priority == 0) {
+ /* no DNS priority for this address family. Skip it! */
+ goto done;
}
+ changed = TRUE;
+
if (!data) {
data = g_slice_new(NMDnsConfigData);
*data = (NMDnsConfigData){
@@ -1895,13 +1946,26 @@ nm_dns_manager_set_ip_config(NMDnsManager * self,
}
if (!ip_data)
- ip_data = _dns_config_ip_data_new(data, ip_config, ip_config_type);
+ ip_data = _dns_config_ip_data_new(data, addr_family, source_tag, l3cd, ip_config_type);
else
ip_data->ip_config_type = ip_config_type;
- priv->ip_config_lst_need_sort = TRUE;
+ priv->ip_data_lst_need_sort = TRUE;
+
+ nm_assert(l3cd);
+ nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ nm_assert(ip_data->addr_family == addr_family);
+ nm_assert(ip_data->source_tag == source_tag);
+ nm_assert(ip_data->l3cd == l3cd);
+ nm_assert(ip_data->ip_config_type == ip_config_type);
+
+done:
+ if (!changed)
+ return FALSE;
+
+ if (data && c_list_is_empty(&data->data_lst_head))
+ g_hash_table_remove(priv->configs_dict, &ifindex);
-changed:
if (!priv->updates_queue) {
gs_free_error GError *error = NULL;
@@ -2415,51 +2479,54 @@ _get_config_variant(NMDnsManager *self)
g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}"));
- head = _mgr_get_ip_config_lst_head(self);
- c_list_for_each_entry (ip_data, head, ip_config_lst) {
- const NMIPConfig *ip_config = ip_data->ip_config;
- GVariantBuilder entry_builder;
- GVariantBuilder strv_builder;
- guint i, num;
- const int addr_family = nm_ip_config_get_addr_family(ip_config);
- char buf[NM_UTILS_INET_ADDRSTRLEN];
- const NMIPAddr * addr;
- const char * ifname;
-
- num = nm_ip_config_get_num_nameservers(ip_config);
- if (!num)
+ head = _mgr_get_ip_data_lst_head(self);
+ c_list_for_each_entry (ip_data, head, ip_data_lst) {
+ GVariantBuilder entry_builder;
+ GVariantBuilder strv_builder;
+ guint num;
+ guint num_domains;
+ guint num_searches;
+ guint i;
+ char buf[NM_UTILS_INET_ADDRSTRLEN];
+ const char * ifname;
+ gconstpointer nameservers;
+
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &num);
+ if (num == 0)
continue;
g_variant_builder_init(&entry_builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as"));
for (i = 0; i < num; i++) {
- addr = nm_ip_config_get_nameserver(ip_config, i);
- g_variant_builder_add(&strv_builder, "s", nm_utils_inet_ntop(addr_family, addr, buf));
+ const NMIPAddr *addr;
+
+ addr = nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i);
+ g_variant_builder_add(&strv_builder,
+ "s",
+ nm_utils_inet_ntop(ip_data->addr_family, addr, buf));
}
g_variant_builder_add(&entry_builder,
"{sv}",
"nameservers",
g_variant_builder_end(&strv_builder));
- num = nm_ip_config_get_num_domains(ip_config);
- num += nm_ip_config_get_num_searches(ip_config);
+ nm_l3_config_data_get_domains(ip_data->l3cd, ip_data->addr_family, &num_domains);
+ nm_l3_config_data_get_searches(ip_data->l3cd, ip_data->addr_family, &num_searches);
+ num = num_domains + num_searches;
if (num > 0) {
if (!array_domains)
array_domains = g_ptr_array_sized_new(num);
else
g_ptr_array_set_size(array_domains, 0);
- add_dns_domains(array_domains, ip_config, TRUE, FALSE);
+ add_dns_domains(array_domains, ip_data->addr_family, ip_data->l3cd, TRUE, FALSE);
if (array_domains->len) {
- g_variant_builder_init(&strv_builder, G_VARIANT_TYPE("as"));
- for (i = 0; i < array_domains->len; i++) {
- g_variant_builder_add(&strv_builder, "s", array_domains->pdata[i]);
- }
g_variant_builder_add(&entry_builder,
"{sv}",
"domains",
- g_variant_builder_end(&strv_builder));
+ g_variant_new_strv((const char *const *) array_domains->pdata,
+ array_domains->len));
}
}
@@ -2474,7 +2541,7 @@ _get_config_variant(NMDnsManager *self)
g_variant_builder_add(&entry_builder,
"{sv}",
"priority",
- g_variant_new_int32(nm_ip_config_get_dns_priority(ip_config)));
+ g_variant_new_int32(_dns_config_ip_data_get_dns_priority(ip_data)));
g_variant_builder_add(
&entry_builder,
@@ -2521,7 +2588,7 @@ nm_dns_manager_init(NMDnsManager *self)
_LOGT("creating...");
c_list_init(&priv->configs_lst_head);
- c_list_init(&priv->ip_config_lst_head);
+ c_list_init(&priv->ip_data_lst_head);
priv->config = g_object_ref(nm_config_get());
@@ -2559,7 +2626,7 @@ dispose(GObject *object)
g_clear_object(&priv->sd_resolve_plugin);
_clear_plugin(self);
- c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst)
+ c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_data_lst_head, ip_data_lst)
_dns_config_ip_data_free(ip_data);
nm_clear_pointer(&priv->configs_dict, g_hash_table_destroy);
diff --git a/src/core/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h
index 501085f701..b462a5fd20 100644
--- a/src/core/dns/nm-dns-manager.h
+++ b/src/core/dns/nm-dns-manager.h
@@ -8,8 +8,7 @@
#ifndef __NETWORKMANAGER_DNS_MANAGER_H__
#define __NETWORKMANAGER_DNS_MANAGER_H__
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
+#include "c-list/src/c-list.h"
#include "nm-setting-connection.h"
#include "nm-dns-plugin.h"
@@ -33,10 +32,12 @@ struct _NMDnsManager;
typedef struct {
struct _NMDnsConfigData *data;
- NMIPConfig * ip_config;
+ gconstpointer source_tag;
+ const NML3ConfigData * l3cd;
CList data_lst;
- CList ip_config_lst;
+ CList ip_data_lst;
NMDnsIPConfigType ip_config_type;
+ int addr_family;
struct {
const char **search;
char ** reverse;
@@ -102,9 +103,12 @@ NMDnsManager *nm_dns_manager_get(void);
void nm_dns_manager_begin_updates(NMDnsManager *self, const char *func);
void nm_dns_manager_end_updates(NMDnsManager *self, const char *func);
-gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type);
+gboolean nm_dns_manager_set_ip_config(NMDnsManager * self,
+ int addr_family,
+ gconstpointer source_tag,
+ const NML3ConfigData *l3cd,
+ NMDnsIPConfigType ip_config_type,
+ gboolean replace_all);
void nm_dns_manager_set_initial_hostname(NMDnsManager *self, const char *hostname);
void nm_dns_manager_set_hostname(NMDnsManager *self, const char *hostname, gboolean skip_update);
diff --git a/src/core/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c
index 5d2eff0be2..8d91bd246e 100644
--- a/src/core/dns/nm-dns-systemd-resolved.c
+++ b/src/core/dns/nm-dns-systemd-resolved.c
@@ -21,10 +21,9 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "libnm-platform/nm-platform.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dbus-manager.h"
#include "nm-manager.h"
+#include "nm-l3-config-data.h"
#include "nm-setting-connection.h"
#include "devices/nm-device.h"
#include "NetworkManagerUtils.h"
@@ -230,40 +229,42 @@ static gboolean
update_add_ip_config(NMDnsSystemdResolved *self,
GVariantBuilder * dns,
GVariantBuilder * domains,
- NMDnsConfigIPData * data)
+ NMDnsConfigIPData * ip_data)
{
- int addr_family;
- gsize addr_size;
- guint i, n;
- gboolean is_routing;
- const char *domain;
- gboolean has_config = FALSE;
-
- addr_family = nm_ip_config_get_addr_family(data->ip_config);
- addr_size = nm_utils_addr_family_to_size(addr_family);
-
- if ((!data->domains.search || !data->domains.search[0])
- && !data->domains.has_default_route_exclusive && !data->domains.has_default_route)
+ gsize addr_size;
+ guint n;
+ guint i;
+ gboolean is_routing;
+ const char * domain;
+ gboolean has_config = FALSE;
+ gconstpointer nameservers;
+
+ addr_size = nm_utils_addr_family_to_size(ip_data->addr_family);
+
+ if ((!ip_data->domains.search || !ip_data->domains.search[0])
+ && !ip_data->domains.has_default_route_exclusive && !ip_data->domains.has_default_route)
return FALSE;
- n = nm_ip_config_get_num_nameservers(data->ip_config);
+ nameservers = nm_l3_config_data_get_nameservers(ip_data->l3cd, ip_data->addr_family, &n);
for (i = 0; i < n; i++) {
g_variant_builder_open(dns, G_VARIANT_TYPE("(iay)"));
- g_variant_builder_add(dns, "i", addr_family);
+ g_variant_builder_add(dns, "i", ip_data->addr_family);
g_variant_builder_add_value(
dns,
- nm_g_variant_new_ay(nm_ip_config_get_nameserver(data->ip_config, i), addr_size));
+ nm_g_variant_new_ay(nm_ip_addr_from_packed_array(ip_data->addr_family, nameservers, i),
+ addr_size));
g_variant_builder_close(dns);
has_config = TRUE;
}
- if (!data->domains.has_default_route_explicit && data->domains.has_default_route_exclusive) {
+ if (!ip_data->domains.has_default_route_explicit
+ && ip_data->domains.has_default_route_exclusive) {
g_variant_builder_add(domains, "(sb)", ".", TRUE);
has_config = TRUE;
}
- if (data->domains.search) {
- for (i = 0; data->domains.search[i]; i++) {
- domain = nm_utils_parse_dns_domain(data->domains.search[i], &is_routing);
+ if (ip_data->domains.search) {
+ for (i = 0; ip_data->domains.search[i]; i++) {
+ domain = nm_utils_parse_dns_domain(ip_data->domains.search[i], &is_routing);
g_variant_builder_add(domains, "(sb)", domain[0] ? domain : ".", is_routing);
has_config = TRUE;
}
@@ -304,17 +305,16 @@ prepare_one_interface(NMDnsSystemdResolved *self, InterfaceConfig *ic)
g_variant_builder_open(&domains, G_VARIANT_TYPE("a(sb)"));
c_list_for_each_entry (elem, &ic->configs_lst_head, lst) {
- NMDnsConfigIPData *data = elem->data;
- NMIPConfig * ip_config = data->ip_config;
+ NMDnsConfigIPData *ip_data = elem->data;
- has_config |= update_add_ip_config(self, &dns, &domains, data);
+ has_config |= update_add_ip_config(self, &dns, &domains, ip_data);
- if (data->domains.has_default_route)
+ if (ip_data->domains.has_default_route)
has_default_route = TRUE;
- if (NM_IS_IP4_CONFIG(ip_config)) {
- mdns = NM_MAX(mdns, nm_ip4_config_mdns_get(NM_IP4_CONFIG(ip_config)));
- llmnr = NM_MAX(llmnr, nm_ip4_config_llmnr_get(NM_IP4_CONFIG(ip_config)));
+ if (NM_IS_IPv4(ip_data->addr_family)) {
+ mdns = NM_MAX(mdns, nm_l3_config_data_get_mdns(ip_data->l3cd));
+ llmnr = NM_MAX(llmnr, nm_l3_config_data_get_llmnr(ip_data->l3cd));
}
}
@@ -508,7 +508,7 @@ start_resolve:
static gboolean
update(NMDnsPlugin * plugin,
const NMGlobalDnsConfig *global_config,
- const CList * ip_config_lst_head,
+ const CList * ip_data_lst_head,
const char * hostname,
GError ** error)
{
@@ -526,11 +526,11 @@ update(NMDnsPlugin * plugin,
interfaces =
g_hash_table_new_full(nm_direct_hash, NULL, NULL, (GDestroyNotify) _interface_config_free);
- c_list_for_each_entry (ip_data, ip_config_lst_head, ip_config_lst) {
+ c_list_for_each_entry (ip_data, ip_data_lst_head, ip_data_lst) {
InterfaceConfig *ic = NULL;
ifindex = ip_data->data->ifindex;
- nm_assert(ifindex == nm_ip_config_get_ifindex(ip_data->ip_config));
+ nm_assert(ifindex == nm_l3_config_data_get_ifindex(ip_data->l3cd));
ic = g_hash_table_lookup(interfaces, GINT_TO_POINTER(ifindex));
if (!ic) {
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 f935ed1606..0c48307004 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -53,8 +53,6 @@ libNetworkManagerBase = static_library(
'nm-l3-ipv4ll.c',
'nm-l3cfg.c',
'nm-ip-config.c',
- 'nm-ip4-config.c',
- 'nm-ip6-config.c',
),
dependencies: [
core_default_dep,
@@ -92,7 +90,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',
@@ -168,7 +165,6 @@ libNetworkManager = static_library(
'nm-manager.c',
'nm-pacrunner-manager.c',
'nm-policy.c',
- 'nm-proxy-config.c',
'nm-rfkill-manager.c',
'nm-session-monitor.c',
'nm-sleep-monitor.c',
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index 4bfd5da186..ee62f62825 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"
@@ -111,8 +112,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)
{
@@ -174,8 +173,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);
@@ -188,8 +189,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++) {
@@ -991,30 +994,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 968f739ee2..3b1ccebe4e 100644
--- a/src/core/ndisc/nm-ndisc.h
+++ b/src/core/ndisc/nm-ndisc.h
@@ -228,10 +228,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);
@@ -272,8 +269,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 d0a2e0c783..58dd4a87f8 100644
--- a/src/core/nm-act-request.c
+++ b/src/core/nm-act-request.c
@@ -24,8 +24,7 @@
#include "settings/nm-settings-connection.h"
typedef struct {
- CList call_ids_lst_head;
- NMFirewallConfig *firewall_config;
+ CList call_ids_lst_head;
} NMActRequestPrivate;
struct _NMActRequest {
@@ -250,36 +249,6 @@ nm_act_request_clear_secrets(NMActRequest *self)
/*****************************************************************************/
-NMFirewallConfig *
-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)->firewall_config;
-}
-
-void
-nm_act_request_set_shared(NMActRequest *req, NMFirewallConfig *rules)
-{
- NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req);
-
- g_return_if_fail(NM_IS_ACT_REQUEST(req));
-
- if (priv->firewall_config == rules)
- return;
-
- if (priv->firewall_config) {
- nm_firewall_config_apply(priv->firewall_config, FALSE);
- priv->firewall_config = NULL;
- }
- if (rules) {
- priv->firewall_config = rules;
- nm_firewall_config_apply(priv->firewall_config, TRUE);
- }
-}
-
-/*****************************************************************************/
-
static void
device_notify(GObject *object, GParamSpec *pspec, gpointer self)
{
@@ -508,11 +477,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->firewall_config) {
- nm_firewall_config_apply(priv->firewall_config, FALSE);
- nm_clear_pointer(&priv->firewall_config, nm_firewall_config_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 9c702d31eb..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 _NMFirewallConfig;
-
-struct _NMFirewallConfig *nm_act_request_get_shared(NMActRequest *req);
-
-void nm_act_request_set_shared(NMActRequest *req, struct _NMFirewallConfig *rules);
-
-/*****************************************************************************/
-
/* Secrets handling */
typedef void (*NMActRequestSecretsFunc)(NMActRequest * req,
diff --git a/src/core/nm-connectivity.c b/src/core/nm-connectivity.c
index 13fb026514..230c4afe53 100644
--- a/src/core/nm-connectivity.c
+++ b/src/core/nm-connectivity.c
@@ -15,6 +15,7 @@
#include <linux/rtnetlink.h>
#include "c-list/src/c-list.h"
+#include "libnm-platform/nmp-object.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
diff --git a/src/core/nm-dhcp-config.c b/src/core/nm-dhcp-config.c
index 8a02911942..ce9f4fbbfb 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 *l3cd_old = 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_strdict_to_variant_asv(options));
+ if (priv->l3cd == l3cd)
+ return;
+
+ l3cd_old = g_steal_pointer(&priv->l3cd);
+ if (l3cd)
+ priv->l3cd = nm_l3_config_data_ref_and_seal(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_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 b77197863b..d68dab5b22 100644
--- a/src/core/nm-dispatcher.c
+++ b/src/core/nm-dispatcher.c
@@ -15,9 +15,7 @@
#include "nm-act-request.h"
#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"
@@ -148,50 +146,47 @@ _init_dispatcher(void)
/*****************************************************************************/
static void
-dump_proxy_to_props(NMProxyConfig *proxy, GVariantBuilder *builder)
+dump_proxy_to_props(const NML3ConfigData *l3cd, GVariantBuilder *builder)
{
- const char *pac_url = NULL, *pac_script = NULL;
+ const char *s;
- if (nm_proxy_config_get_method(proxy) == NM_PROXY_CONFIG_METHOD_NONE)
+ if (nm_l3_config_data_get_proxy_method(l3cd) != NM_PROXY_CONFIG_METHOD_AUTO)
return;
- pac_url = nm_proxy_config_get_pac_url(proxy);
- if (pac_url) {
- g_variant_builder_add(builder, "{sv}", "pac-url", g_variant_new_string(pac_url));
- }
+ s = nm_l3_config_data_get_proxy_pac_url(l3cd);
+ if (s)
+ g_variant_builder_add(builder, "{sv}", "pac-url", g_variant_new_string(s));
- pac_script = nm_proxy_config_get_pac_script(proxy);
- if (pac_script) {
- g_variant_builder_add(builder, "{sv}", "pac-script", g_variant_new_string(pac_script));
- }
+ s = nm_l3_config_data_get_proxy_pac_script(l3cd);
+ if (s)
+ g_variant_builder_add(builder, "{sv}", "pac-script", g_variant_new_string(s));
}
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 +220,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 +249,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 +289,8 @@ 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;
+ 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,
@@ -329,17 +317,12 @@ fill_device_props(NMDevice * device,
g_variant_new_object_path(nm_dbus_object_get_path(NM_DBUS_OBJECT(device))));
}
- proxy_config = nm_device_get_proxy_config(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);
+ dump_proxy_to_props(l3cd, proxy_builder);
+ }
dhcp_config = nm_device_get_dhcp_config(device, AF_INET);
if (dhcp_config)
@@ -351,19 +334,16 @@ 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(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);
+ dump_proxy_to_props(l3cd, proxy_builder);
+ }
}
static const char *
@@ -479,9 +459,7 @@ _dispatcher_call(NMDispatcherAction action,
gboolean activation_type_external,
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,13 +571,8 @@ _dispatcher_call(NMDispatcherAction action,
&device_ip6_props,
&device_dhcp4_props,
&device_dhcp6_props);
- if (vpn_ip4_config || vpn_ip6_config) {
- fill_vpn_props(vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
- &vpn_proxy_props,
- &vpn_ip4_props,
- &vpn_ip6_props);
+ if (l3cd) {
+ fill_vpn_props(l3cd, &vpn_proxy_props, &vpn_ip4_props, &vpn_ip6_props);
}
}
@@ -693,8 +666,6 @@ nm_dispatcher_call_hostname(NMDispatcherFunc callback,
NM_CONNECTIVITY_UNKNOWN,
NULL,
NULL,
- NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -744,8 +715,6 @@ nm_dispatcher_call_device(NMDispatcherAction action,
NM_CONNECTIVITY_UNKNOWN,
NULL,
NULL,
- NULL,
- NULL,
callback,
user_data,
out_call_id);
@@ -790,8 +759,6 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
NULL,
NULL,
NULL,
- NULL,
- NULL,
NULL);
}
@@ -802,9 +769,7 @@ nm_dispatcher_call_device_sync(NMDispatcherAction action,
* @applied_connection: the currently applied connection
* @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
@@ -821,9 +786,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
NMConnection * applied_connection,
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)
@@ -836,9 +799,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
FALSE,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
- vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
callback,
user_data,
out_call_id);
@@ -851,9 +812,7 @@ nm_dispatcher_call_vpn(NMDispatcherAction action,
* @applied_connection: the currently applied connection
* @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.
@@ -866,9 +825,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMConnection * applied_connection,
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,
@@ -878,9 +835,7 @@ nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
FALSE,
NM_CONNECTIVITY_UNKNOWN,
vpn_iface,
- vpn_proxy_config,
- vpn_ip4_config,
- vpn_ip6_config,
+ l3cd,
NULL,
NULL,
NULL);
@@ -913,8 +868,6 @@ nm_dispatcher_call_connectivity(NMConnectivityState connectivity_state,
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 8e4f01cb62..c347352a2d 100644
--- a/src/core/nm-dispatcher.h
+++ b/src/core/nm-dispatcher.h
@@ -51,9 +51,7 @@ gboolean nm_dispatcher_call_vpn(NMDispatcherAction action,
NMConnection * applied_connection,
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);
@@ -63,9 +61,7 @@ gboolean nm_dispatcher_call_vpn_sync(NMDispatcherAction action,
NMConnection * applied_connection,
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 73000af099..00947e24b8 100644
--- a/src/core/nm-iface-helper.c
+++ b/src/core/nm-iface-helper.c
@@ -89,6 +89,9 @@ static struct {
NULL, \
"iface-helper: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) _NM_UTILS_MACRO_REST(__VA_ARGS__))
+//XXX
+#if 0
+
/*****************************************************************************/
static void
@@ -100,7 +103,8 @@ _dhcp_client_notify_cb(NMDhcpClient * client,
NMIP4Config * existing;
gs_unref_ptrarray GPtrArray *ip4_dev_route_blacklist = NULL;
gs_free_error GError *error = NULL;
- NMIP4Config * ip4_config;
+
+ /* FIXME(l3cfg): fix handling metric_any/table_any for routes. */
if (!notify_data || notify_data->notify_type != NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED)
g_return_if_reached();
@@ -516,10 +520,13 @@ ip6_address_changed(NMPlatform * platform,
data,
nm_g_slice_free_fcn(DadFailedHandleData));
}
+#endif
int
main(int argc, char *argv[])
{
+//XXX
+#if 0
char * bad_domains = NULL;
gs_free_error GError *error = NULL;
gboolean wrote_pidfile = FALSE;
@@ -670,8 +677,6 @@ main(int argc, char *argv[])
hwaddr,
bcast_hwaddr,
global_opt.uuid,
- RT_TABLE_MAIN,
- global_opt.priority_v4,
NM_DHCP_CLIENT_FLAGS_NONE,
!!global_opt.dhcp4_hostname,
global_opt.dhcp4_hostname,
@@ -767,6 +772,7 @@ main(int argc, char *argv[])
nm_clear_g_source(&sd_id);
nm_clear_pointer(&gl.main_loop, g_main_loop_unref);
+#endif
return 0;
}
@@ -859,5 +865,6 @@ nm_device_get_type(void)
GType
nm_active_connection_get_type(void)
{
+ (void) gl; //XXX
g_return_val_if_reached(0);
}
diff --git a/src/core/nm-ip-config.c b/src/core/nm-ip-config.c
index 2426eb4941..f0a93cc4d2 100644
--- a/src/core/nm-ip-config.c
+++ b/src/core/nm-ip-config.c
@@ -12,26 +12,29 @@
/*****************************************************************************/
-NM_GOBJECT_PROPERTIES_DEFINE(NMIPConfig, PROP_L3CFG, PROP_IS_VPN, );
+GType nm_ip4_config_get_type(void);
+GType nm_ip6_config_get_type(void);
-typedef struct _NMIPConfigPrivate {
- NML3Cfg *l3cfg;
- bool is_vpn : 1;
-} NMIPConfigPrivate;
+/*****************************************************************************/
+
+typedef struct _NMIPConfigPrivate NMIPConfigPrivate;
+
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip, NMIPConfig, PROP_IP_L3CFG, PROP_IP_IS_VPN, );
G_DEFINE_ABSTRACT_TYPE(NMIPConfig, nm_ip_config, NM_TYPE_DBUS_OBJECT)
-#define NM_IP_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMIPConfig, NM_IS_IP_CONFIG)
+#define NM_IP_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIPConfig, NM_IS_IP_CONFIG)
/*****************************************************************************/
static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+get_property_ip(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMIPConfig * self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
- (void) priv;
+ (void) priv; //XXX
+
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -44,14 +47,16 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
{
NMIPConfig * self = NM_IP_CONFIG(object);
NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+ gpointer ptr;
switch (prop_id) {
- case PROP_L3CFG:
+ case PROP_IP_L3CFG:
/* construct-only */
- priv->l3cfg = nm_g_object_ref(g_value_get_pointer(value));
- nm_assert(!priv->l3cfg || NM_IS_L3CFG(priv->l3cfg));
+ ptr = g_value_get_pointer(value);
+ nm_assert(NM_IS_L3CFG(ptr));
+ priv->l3cfg = g_object_ref(ptr);
break;
- case PROP_IS_VPN:
+ case PROP_IP_IS_VPN:
/* construct-only */
priv->is_vpn = g_value_get_boolean(value);
break;
@@ -65,13 +70,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps
static void
nm_ip_config_init(NMIPConfig *self)
-{
- NMIPConfigPrivate *priv;
-
- priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_IP_CONFIG, NMIPConfigPrivate);
-
- self->_priv = priv;
-}
+{}
NMIPConfig *
nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn)
@@ -88,13 +87,25 @@ nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn)
NULL);
}
+void
+nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take)
+{
+ if (!self_take)
+ return;
+
+ //XXX: freeze the instance so that no more signals are emitted while
+ // the instance gets unexported.
+
+ nm_dbus_object_unexport_on_idle(g_steal_pointer(&self_take));
+}
+
static void
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);
}
@@ -102,26 +113,420 @@ finalize(GObject *object)
static void
nm_ip_config_class_init(NMIPConfigClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- g_type_class_add_private(object_class, sizeof(NMIPConfigPrivate));
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- object_class->get_property = get_property;
+ object_class->get_property = get_property_ip;
object_class->set_property = set_property;
object_class->finalize = finalize;
- obj_properties[PROP_L3CFG] =
+ dbus_object_class->export_on_construction = TRUE;
+
+ obj_properties_ip[PROP_IP_L3CFG] =
g_param_spec_pointer(NM_IP_CONFIG_L3CFG,
"",
"",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IS_VPN] =
+ obj_properties_ip[PROP_IP_IS_VPN] =
g_param_spec_boolean(NM_IP_CONFIG_IS_VPN,
"",
"",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip, obj_properties_ip);
+}
+
+/*****************************************************************************/
+
+/* public*/
+#define NM_IP4_CONFIG_ADDRESS_DATA "address-data"
+#define NM_IP4_CONFIG_DNS_OPTIONS "dns-options"
+#define NM_IP4_CONFIG_DNS_PRIORITY "dns-priority"
+#define NM_IP4_CONFIG_DOMAINS "domains"
+#define NM_IP4_CONFIG_GATEWAY "gateway"
+#define NM_IP4_CONFIG_NAMESERVER_DATA "nameserver-data"
+#define NM_IP4_CONFIG_ROUTE_DATA "route-data"
+#define NM_IP4_CONFIG_SEARCHES "searches"
+#define NM_IP4_CONFIG_WINS_SERVER_DATA "wins-server-data"
+
+/* deprecated */
+#define NM_IP4_CONFIG_ADDRESSES "addresses"
+#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP4_CONFIG_ROUTES "routes"
+#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
+
+typedef struct _NMIP4Config NMIP4Config;
+typedef struct _NMIP4ConfigClass NMIP4ConfigClass;
+
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip4,
+ NMIP4Config,
+ PROP_IP4_ADDRESSES,
+ PROP_IP4_ADDRESS_DATA,
+ PROP_IP4_DNS_OPTIONS,
+ PROP_IP4_DNS_PRIORITY,
+ PROP_IP4_DOMAINS,
+ PROP_IP4_GATEWAY,
+ PROP_IP4_NAMESERVERS,
+ PROP_IP4_NAMESERVER_DATA,
+ PROP_IP4_ROUTES,
+ PROP_IP4_ROUTE_DATA,
+ PROP_IP4_SEARCHES,
+ PROP_IP4_WINS_SERVERS,
+ PROP_IP4_WINS_SERVER_DATA, );
+
+struct _NMIP4Config {
+ NMIPConfig parent;
+};
+
+struct _NMIP4ConfigClass {
+ NMIPConfigClass parent;
+};
+
+G_DEFINE_TYPE(NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
+
+static void
+get_property_ip4(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+
+ (void) priv; //XXX
+
+ switch (prop_id) {
+ default:
+ return; //XXX
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
+ .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
+ NM_DBUS_INTERFACE_IP4_CONFIG,
+ .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
+ "aau",
+ NM_IP4_CONFIG_ADDRESSES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
+ "aa{sv}",
+ NM_IP4_CONFIG_ADDRESS_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP4_CONFIG_GATEWAY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", "aau", NM_IP4_CONFIG_ROUTES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
+ "aa{sv}",
+ NM_IP4_CONFIG_ROUTE_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData",
+ "aa{sv}",
+ NM_IP4_CONFIG_NAMESERVER_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
+ "au",
+ NM_IP4_CONFIG_NAMESERVERS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP4_CONFIG_DOMAINS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
+ "as",
+ NM_IP4_CONFIG_SEARCHES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
+ "as",
+ NM_IP4_CONFIG_DNS_OPTIONS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
+ "i",
+ NM_IP4_CONFIG_DNS_PRIORITY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData",
+ "as",
+ NM_IP4_CONFIG_WINS_SERVER_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServers",
+ "au",
+ NM_IP4_CONFIG_WINS_SERVERS), ), ),
+};
+
+static void
+nm_ip4_config_init(NMIP4Config *self)
+{}
+
+static void
+nm_ip4_config_class_init(NMIP4ConfigClass *klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+ NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
+
+ ip_config_class->addr_family = AF_INET;
+
+ dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP4Config");
+ dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip4_config);
+
+ object_class->get_property = get_property_ip4;
+
+ obj_properties_ip4[PROP_IP4_ADDRESS_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_ADDRESS_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_ADDRESSES] =
+ g_param_spec_variant(NM_IP4_CONFIG_ADDRESSES,
+ "",
+ "",
+ G_VARIANT_TYPE("aau"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_ROUTE_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_ROUTE_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_ROUTES] =
+ g_param_spec_variant(NM_IP4_CONFIG_ROUTES,
+ "",
+ "",
+ G_VARIANT_TYPE("aau"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_GATEWAY] =
+ g_param_spec_string(NM_IP4_CONFIG_GATEWAY,
+ "",
+ "",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_NAMESERVER_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_NAMESERVER_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_NAMESERVERS] =
+ g_param_spec_variant(NM_IP4_CONFIG_NAMESERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("au"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_DOMAINS] =
+ g_param_spec_boxed(NM_IP4_CONFIG_DOMAINS,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_SEARCHES] =
+ g_param_spec_boxed(NM_IP4_CONFIG_SEARCHES,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_DNS_OPTIONS] =
+ g_param_spec_boxed(NM_IP4_CONFIG_DNS_OPTIONS,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_DNS_PRIORITY] =
+ g_param_spec_int(NM_IP4_CONFIG_DNS_PRIORITY,
+ "",
+ "",
+ G_MININT32,
+ G_MAXINT32,
+ 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_WINS_SERVER_DATA] =
+ g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVER_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("as"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip4[PROP_IP4_WINS_SERVERS] =
+ g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("au"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip4, obj_properties_ip4);
+}
+
+/*****************************************************************************/
+
+/* public */
+#define NM_IP6_CONFIG_ADDRESS_DATA "address-data"
+#define NM_IP6_CONFIG_ROUTE_DATA "route-data"
+#define NM_IP6_CONFIG_GATEWAY "gateway"
+#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
+#define NM_IP6_CONFIG_DOMAINS "domains"
+#define NM_IP6_CONFIG_SEARCHES "searches"
+#define NM_IP6_CONFIG_DNS_OPTIONS "dns-options"
+#define NM_IP6_CONFIG_DNS_PRIORITY "dns-priority"
+
+/* deprecated */
+#define NM_IP6_CONFIG_ADDRESSES "addresses"
+#define NM_IP6_CONFIG_ROUTES "routes"
+
+typedef struct _NMIP6Config NMIP6Config;
+typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
+
+NM_GOBJECT_PROPERTIES_DEFINE_FULL(_ip6,
+ NMIP6Config,
+ PROP_IP6_ADDRESS_DATA,
+ PROP_IP6_ROUTE_DATA,
+ PROP_IP6_GATEWAY,
+ PROP_IP6_NAMESERVERS,
+ PROP_IP6_DOMAINS,
+ PROP_IP6_SEARCHES,
+ PROP_IP6_DNS_OPTIONS,
+ PROP_IP6_DNS_PRIORITY,
+ PROP_IP6_ADDRESSES,
+ PROP_IP6_ROUTES, );
+
+struct _NMIP6Config {
+ NMIPConfig parent;
+};
+
+struct _NMIP6ConfigClass {
+ NMIPConfigClass parent;
+};
+
+G_DEFINE_TYPE(NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
+
+static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
+ .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
+ NM_DBUS_INTERFACE_IP6_CONFIG,
+ .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
+ "a(ayuay)",
+ NM_IP6_CONFIG_ADDRESSES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
+ "aa{sv}",
+ NM_IP6_CONFIG_ADDRESS_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP6_CONFIG_GATEWAY),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes",
+ "a(ayuayu)",
+ NM_IP6_CONFIG_ROUTES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
+ "aa{sv}",
+ NM_IP6_CONFIG_ROUTE_DATA),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
+ "aay",
+ NM_IP6_CONFIG_NAMESERVERS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP6_CONFIG_DOMAINS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
+ "as",
+ NM_IP6_CONFIG_SEARCHES),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
+ "as",
+ NM_IP6_CONFIG_DNS_OPTIONS),
+ NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
+ "i",
+ NM_IP6_CONFIG_DNS_PRIORITY), ), ),
+};
+
+static void
+get_property_ip6(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ NMIPConfig * self = NM_IP_CONFIG(object);
+ NMIPConfigPrivate *priv = NM_IP_CONFIG_GET_PRIVATE(self);
+
+ (void) priv; //XXX
+
+ switch (prop_id) {
+ //XXX
+ default:
+ return; //XXX
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_ip6_config_init(NMIP6Config *self)
+{}
+
+static void
+nm_ip6_config_class_init(NMIP6ConfigClass *klass)
+{
+ GObjectClass * object_class = G_OBJECT_CLASS(klass);
+ NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
+ NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
+
+ ip_config_class->addr_family = AF_INET6;
+
+ dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP6Config");
+ dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip6_config);
+
+ object_class->get_property = get_property_ip6;
+
+ obj_properties_ip6[PROP_IP6_ADDRESS_DATA] =
+ g_param_spec_variant(NM_IP6_CONFIG_ADDRESS_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_ADDRESSES] =
+ g_param_spec_variant(NM_IP6_CONFIG_ADDRESSES,
+ "",
+ "",
+ G_VARIANT_TYPE("a(ayuay)"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_ROUTE_DATA] =
+ g_param_spec_variant(NM_IP6_CONFIG_ROUTE_DATA,
+ "",
+ "",
+ G_VARIANT_TYPE("aa{sv}"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_ROUTES] =
+ g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
+ "",
+ "",
+ G_VARIANT_TYPE("a(ayuayu)"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_GATEWAY] =
+ g_param_spec_string(NM_IP6_CONFIG_GATEWAY,
+ "",
+ "",
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_NAMESERVERS] =
+ g_param_spec_variant(NM_IP6_CONFIG_NAMESERVERS,
+ "",
+ "",
+ G_VARIANT_TYPE("aay"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_DOMAINS] =
+ g_param_spec_boxed(NM_IP6_CONFIG_DOMAINS,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_SEARCHES] =
+ g_param_spec_boxed(NM_IP6_CONFIG_SEARCHES,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_DNS_OPTIONS] =
+ g_param_spec_boxed(NM_IP6_CONFIG_DNS_OPTIONS,
+ "",
+ "",
+ G_TYPE_STRV,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+ obj_properties_ip6[PROP_IP6_DNS_PRIORITY] =
+ g_param_spec_int(NM_IP6_CONFIG_DNS_PRIORITY,
+ "",
+ "",
+ G_MININT32,
+ G_MAXINT32,
+ 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST_ip6, obj_properties_ip6);
}
diff --git a/src/core/nm-ip-config.h b/src/core/nm-ip-config.h
index 8e1a593412..6e4022b5e0 100644
--- a/src/core/nm-ip-config.h
+++ b/src/core/nm-ip-config.h
@@ -7,6 +7,7 @@
#define __NM_IP_CONFIG_H__
#include "nm-dbus-object.h"
+#include "nm-l3cfg.h"
/*****************************************************************************/
@@ -22,23 +23,55 @@
#define NM_IP_CONFIG_L3CFG "l3cfg"
#define NM_IP_CONFIG_IS_VPN "is-vpn"
-struct _NMIPConfigPrivate;
+struct _NMIPConfigPrivate {
+ NML3Cfg *l3cfg;
+ bool is_vpn : 1;
+};
struct _NMIPConfig {
- NMDBusObject parent;
- struct _NMIPConfigPrivate *_priv;
+ NMDBusObject parent;
+ struct _NMIPConfigPrivate _priv;
};
typedef struct {
NMDBusObjectClass parent;
- gboolean is_ipv4;
int addr_family;
} NMIPConfigClass;
GType nm_ip_config_get_type(void);
-GType nm_ip4_config_get_type(void);
-GType nm_ip6_config_get_type(void);
NMIPConfig *nm_ip_config_new(int addr_family, NML3Cfg *l3cfg, gboolean is_vpn);
+void nm_ip_config_take_and_unexport_on_idle(NMIPConfig *self_take);
+
+/*****************************************************************************/
+
+static inline NML3Cfg *
+nm_ip_config_get_l3cfg(NMIPConfig *self)
+{
+ g_return_val_if_fail(NM_IS_IP_CONFIG(self), NULL);
+
+ return self->_priv.l3cfg;
+}
+
+static inline struct _NMDedupMultiIndex *
+nm_ip_config_get_multi_index(NMIPConfig *self)
+{
+ return nm_l3cfg_get_multi_idx(nm_ip_config_get_l3cfg(self));
+}
+
+static inline int
+nm_ip_config_get_ifindex(NMIPConfig *self)
+{
+ return nm_l3cfg_get_ifindex(nm_ip_config_get_l3cfg(self));
+}
+
+static inline int
+nm_ip_config_get_addr_family(NMIPConfig *self)
+{
+ g_return_val_if_fail(NM_IS_IP_CONFIG(self), AF_UNSPEC);
+
+ return NM_IP_CONFIG_GET_CLASS(self)->addr_family;
+}
+
#endif /* __NM_IP_CONFIG_H__ */
diff --git a/src/core/nm-ip4-config.c b/src/core/nm-ip4-config.c
deleted file mode 100644
index 3d1e489a59..0000000000
--- a/src/core/nm-ip4-config.c
+++ /dev/null
@@ -1,3322 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2005 - 2017 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-ip4-config.h"
-
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <linux/rtnetlink.h>
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-
-#include "nm-utils.h"
-#include "libnm-platform/nmp-object.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nm-platform-utils.h"
-#include "NetworkManagerUtils.h"
-#include "libnm-core-intern/nm-core-internal.h"
-#include "nm-dbus-object.h"
-
-/*****************************************************************************/
-
-/* internal guint32 are assigned to gobject properties of type uint. Ensure, that uint is large enough */
-G_STATIC_ASSERT(sizeof(uint) >= sizeof(guint32));
-G_STATIC_ASSERT(G_MAXUINT >= 0xFFFFFFFF);
-
-/*****************************************************************************/
-
-static gboolean
-_route_valid(const NMPlatformIP4Route *r)
-{
- return r && r->plen <= 32
- && r->network == nm_utils_ip4_address_clear_host_address(r->network, r->plen);
-}
-
-/*****************************************************************************/
-
-static void
-_idx_obj_id_hash_update(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj,
- NMHashState * h)
-{
- nmp_object_id_hash_update((NMPObject *) obj, h);
-}
-
-static gboolean
-_idx_obj_id_equal(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj_a,
- const NMDedupMultiObj * obj_b)
-{
- return nmp_object_id_equal((NMPObject *) obj_a, (NMPObject *) obj_b);
-}
-
-void
-nm_ip_config_dedup_multi_idx_type_init(NMIPConfigDedupMultiIdxType *idx_type,
- NMPObjectType obj_type)
-{
- static const NMDedupMultiIdxTypeClass idx_type_class = {
- .idx_obj_id_hash_update = _idx_obj_id_hash_update,
- .idx_obj_id_equal = _idx_obj_id_equal,
- };
-
- nm_dedup_multi_idx_type_init((NMDedupMultiIdxType *) idx_type, &idx_type_class);
- idx_type->obj_type = obj_type;
-}
-
-/*****************************************************************************/
-
-gboolean
-_nm_ip_config_add_obj(NMDedupMultiIndex * multi_idx,
- NMIPConfigDedupMultiIdxType *idx_type,
- int ifindex,
- const NMPObject * obj_new,
- const NMPlatformObject * pl_new,
- gboolean merge,
- gboolean append_force,
- const NMPObject ** out_obj_old /* returns a reference! */,
- const NMPObject ** out_obj_new /* does not return a reference */)
-{
- NMPObject obj_new_stackinit;
- const NMDedupMultiEntry *entry_old;
- const NMDedupMultiEntry *entry_new;
-
- nm_assert(multi_idx);
- nm_assert(idx_type);
- nm_assert(NM_IN_SET(idx_type->obj_type,
- NMP_OBJECT_TYPE_IP4_ADDRESS,
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ADDRESS,
- NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(ifindex > 0);
-
- /* we go through extra lengths to accept a full obj_new object. That one,
- * can be reused by increasing the ref-count. */
- if (!obj_new) {
- nm_assert(pl_new);
- obj_new = nmp_object_stackinit(&obj_new_stackinit, idx_type->obj_type, pl_new);
- NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
- } else {
- nm_assert(!pl_new);
- nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
- if (NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj_new)->ifindex != ifindex) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(&obj_new_stackinit)->ifindex = ifindex;
- }
- }
- nm_assert(NMP_OBJECT_GET_TYPE(obj_new) == idx_type->obj_type);
- nm_assert(nmp_object_is_alive(obj_new));
-
- entry_old = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, obj_new);
-
- if (entry_old) {
- gboolean modified = FALSE;
- const NMPObject *obj_old = entry_old->obj;
-
- if (nmp_object_equal(obj_new, obj_old)) {
- nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
- goto append_force_and_out;
- }
-
- /* if @merge, we merge the new object with the existing one.
- * Otherwise, we replace it entirely. */
- if (merge) {
- switch (idx_type->obj_type) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- /* for addresses that we read from the kernel, we keep the timestamps as defined
- * by the previous source (item_old). The reason is, that the other source configured the lifetimes
- * with "what should be" and the kernel values are "what turned out after configuring it".
- *
- * For other sources, the longer lifetime wins. */
- if ((obj_new->ip_address.addr_source == NM_IP_CONFIG_SOURCE_KERNEL
- && obj_old->ip_address.addr_source != NM_IP_CONFIG_SOURCE_KERNEL)
- || nm_platform_ip_address_cmp_expiry(NMP_OBJECT_CAST_IP_ADDRESS(obj_old),
- NMP_OBJECT_CAST_IP_ADDRESS(obj_new))
- > 0) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_address.timestamp =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->timestamp;
- obj_new_stackinit.ip_address.lifetime =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->lifetime;
- obj_new_stackinit.ip_address.preferred =
- NMP_OBJECT_CAST_IP_ADDRESS(obj_old)->preferred;
- modified = TRUE;
- }
-
- /* keep the maximum addr_source. */
- if (obj_new->ip_address.addr_source < obj_old->ip_address.addr_source) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_address.addr_source = obj_old->ip_address.addr_source;
- modified = TRUE;
- }
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- /* keep the maximum rt_source. */
- if (obj_new->ip_route.rt_source < obj_old->ip_route.rt_source) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_route.rt_source = obj_old->ip_route.rt_source;
- modified = TRUE;
- }
- if (!obj_new->ip_route.is_external && obj_old->ip_route.is_external) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_route.is_external = FALSE;
- modified = TRUE;
- }
- break;
- default:
- nm_assert_not_reached();
- break;
- }
-
- if (modified && nmp_object_equal(obj_new, obj_old)) {
- nm_dedup_multi_entry_set_dirty(entry_old, FALSE);
- goto append_force_and_out;
- }
- }
- }
-
- if (!nm_dedup_multi_index_add_full(multi_idx,
- &idx_type->parent,
- obj_new,
- append_force ? NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE
- : NM_DEDUP_MULTI_IDX_MODE_APPEND,
- NULL,
- entry_old ?: NM_DEDUP_MULTI_ENTRY_MISSING,
- NULL,
- &entry_new,
- out_obj_old)) {
- nm_assert_not_reached();
- NM_SET_OUT(out_obj_new, NULL);
- return FALSE;
- }
-
- NM_SET_OUT(out_obj_new, entry_new->obj);
- return TRUE;
-
-append_force_and_out:
- NM_SET_OUT(out_obj_old, nmp_object_ref(entry_old->obj));
- NM_SET_OUT(out_obj_new, entry_old->obj);
- if (append_force) {
- if (nm_dedup_multi_entry_reorder(entry_old, NULL, TRUE))
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * _nm_ip_config_lookup_ip_route:
- * @multi_idx:
- * @idx_type:
- * @needle:
- * @cmp_type: after lookup, filter the result by comparing with @cmp_type. Only
- * return the result, if it compares equal to @needle according to this @cmp_type.
- * Note that the index uses %NM_PLATFORM_IP_ROUTE_CMP_TYPE_DST type, so passing
- * that compare-type means not to filter any further.
- *
- * Returns: the found entry or %NULL.
- */
-const NMDedupMultiEntry *
-_nm_ip_config_lookup_ip_route(const NMDedupMultiIndex * multi_idx,
- const NMIPConfigDedupMultiIdxType *idx_type,
- const NMPObject * needle,
- NMPlatformIPRouteCmpType cmp_type)
-{
- const NMDedupMultiEntry *entry;
-
- nm_assert(multi_idx);
- nm_assert(idx_type);
- nm_assert(NM_IN_SET(idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == idx_type->obj_type);
-
- entry = nm_dedup_multi_index_lookup_obj(multi_idx, &idx_type->parent, needle);
- if (!entry)
- return NULL;
-
- if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) {
- nm_assert((NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE
- && nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP4_ROUTE(needle),
- cmp_type)
- == 0)
- || (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP6_ROUTE
- && nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP6_ROUTE(needle),
- cmp_type)
- == 0));
- } else {
- if (NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE) {
- if (nm_platform_ip4_route_cmp(NMP_OBJECT_CAST_IP4_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP4_ROUTE(needle),
- cmp_type)
- != 0)
- return NULL;
- } else {
- if (nm_platform_ip6_route_cmp(NMP_OBJECT_CAST_IP6_ROUTE(entry->obj),
- NMP_OBJECT_CAST_IP6_ROUTE(needle),
- cmp_type)
- != 0)
- return NULL;
- }
- }
- return entry;
-}
-
-/*****************************************************************************/
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config,
- PROP_MULTI_IDX,
- PROP_IFINDEX,
- PROP_ADDRESS_DATA,
- PROP_ADDRESSES,
- PROP_ROUTE_DATA,
- PROP_ROUTES,
- PROP_GATEWAY,
- PROP_NAMESERVER_DATA,
- PROP_NAMESERVERS,
- PROP_DOMAINS,
- PROP_SEARCHES,
- PROP_DNS_OPTIONS,
- PROP_WINS_SERVER_DATA,
- PROP_WINS_SERVERS,
- PROP_DNS_PRIORITY, );
-
-typedef struct {
- bool metered : 1;
- bool never_default : 1;
- guint32 mtu;
- int ifindex;
- NMIPConfigSource mtu_source;
- int dns_priority;
- NMSettingConnectionMdns mdns;
- NMSettingConnectionLlmnr llmnr;
- GArray * nameservers;
- GPtrArray * domains;
- GPtrArray * searches;
- GPtrArray * dns_options;
- GArray * nis;
- char * nis_domain;
- GArray * wins;
- GVariant * address_data_variant;
- GVariant * addresses_variant;
- GVariant * route_data_variant;
- GVariant * routes_variant;
- NMDedupMultiIndex * multi_idx;
- const NMPObject * best_default_route;
- union {
- NMIPConfigDedupMultiIdxType idx_ip4_addresses_;
- NMDedupMultiIdxType idx_ip4_addresses;
- };
- union {
- NMIPConfigDedupMultiIdxType idx_ip4_routes_;
- NMDedupMultiIdxType idx_ip4_routes;
- };
- NMIPConfigFlags config_flags;
-} NMIP4ConfigPrivate;
-
-struct _NMIP4Config {
- NMIPConfig parent;
- NMIP4ConfigPrivate _priv;
-};
-
-struct _NMIP4ConfigClass {
- NMIPConfigClass parent;
-};
-
-G_DEFINE_TYPE(NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
-
-#define NM_IP4_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP4Config, NM_IS_IP4_CONFIG)
-
-/*****************************************************************************/
-
-static void
-_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new);
-static void _add_route(NMIP4Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new);
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-int
-nm_ip4_config_get_ifindex(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex;
-}
-
-NMDedupMultiIndex *
-nm_ip4_config_get_multi_idx(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->multi_idx;
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_addresses(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_addresses, NULL);
-}
-
-void
-nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
-{
- nm_assert(NM_IS_IP4_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_addresses(self));
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip4_config_lookup_routes(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip4_routes, NULL);
-}
-
-void
-nm_ip_config_iter_ip4_route_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self)
-{
- nm_assert(NM_IS_IP4_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_routes(self));
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-_nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur, const NMPObject *obj_cmp)
-{
- nm_assert(!obj_cur
- || NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cur),
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ROUTE));
- nm_assert(!obj_cmp
- || (!obj_cur
- && NM_IN_SET(NMP_OBJECT_GET_TYPE(obj_cmp),
- NMP_OBJECT_TYPE_IP4_ROUTE,
- NMP_OBJECT_TYPE_IP6_ROUTE))
- || NMP_OBJECT_GET_TYPE(obj_cur) == NMP_OBJECT_GET_TYPE(obj_cmp));
- nm_assert(!obj_cur || nmp_object_ip_route_is_best_defaut_route(obj_cur));
-
- /* assumes that @obj_cur is already the best default route (or NULL). It checks whether
- * @obj_cmp is also a default route and returns the best of both. */
- if (obj_cmp && nmp_object_ip_route_is_best_defaut_route(obj_cmp)) {
- guint32 metric_cur, metric_cmp;
-
- if (!obj_cur)
- return obj_cmp;
-
- metric_cur = NMP_OBJECT_CAST_IP_ROUTE(obj_cur)->metric;
- metric_cmp = NMP_OBJECT_CAST_IP_ROUTE(obj_cmp)->metric;
-
- if (metric_cmp < metric_cur)
- return obj_cmp;
-
- if (metric_cmp == metric_cur) {
- int c;
-
- /* Routes have the same metric. We still want to deterministically
- * prefer one or the other. It's important to consistently choose one
- * or the other, so that the order doesn't matter how routes are added
- * (and merged). */
- c = nmp_object_cmp(obj_cur, obj_cmp);
- if (c != 0)
- return c < 0 ? obj_cur : obj_cmp;
-
- /* as last resort, compare pointers. */
- if (obj_cmp < obj_cur)
- return obj_cmp;
- }
- }
- return obj_cur;
-}
-
-gboolean
-_nm_ip_config_best_default_route_merge(const NMPObject **best_default_route,
- const NMPObject * new_candidate)
-{
- new_candidate =
- _nm_ip_config_best_default_route_find_better(*best_default_route, new_candidate);
- return nmp_object_ref_set(best_default_route, new_candidate);
-}
-
-const NMPObject *
-nm_ip4_config_best_default_route_get(const NMIP4Config *self)
-{
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
-
- return NM_IP4_CONFIG_GET_PRIVATE(self)->best_default_route;
-}
-
-const NMPObject *
-_nm_ip4_config_best_default_route_find(const NMIP4Config *self)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPObject *new_best_default_route = NULL;
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, NULL) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route,
- ipconf_iter.current->obj);
- }
- return new_best_default_route;
-}
-
-in_addr_t
-nmtst_ip4_config_get_gateway(NMIP4Config *config)
-{
- const NMPObject *rt;
-
- g_assert(NM_IS_IP4_CONFIG(config));
-
- rt = nm_ip4_config_best_default_route_get(config);
- if (!rt)
- return 0;
- return NMP_OBJECT_CAST_IP4_ROUTE(rt)->gateway;
-}
-
-/*****************************************************************************/
-
-static void
-_notify_addresses(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_gobject_notify_together(self, PROP_ADDRESS_DATA, PROP_ADDRESSES);
-}
-
-static void
-_notify_routes(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_assert(priv->best_default_route == _nm_ip4_config_best_default_route_find(self));
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
- nm_gobject_notify_together(self, PROP_ROUTE_DATA, PROP_ROUTES);
-}
-
-/*****************************************************************************/
-
-static int
-sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data)
-{
- const NMPlatformIP4Address *addr_a =
- NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj);
- const NMPlatformIP4Address *addr_b =
- NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj);
-
- nm_assert(addr_a);
- nm_assert(addr_b);
-
- /* Primary addresses first */
- return NM_FLAGS_HAS(addr_a->n_ifa_flags, IFA_F_SECONDARY)
- - NM_FLAGS_HAS(addr_b->n_ifa_flags, IFA_F_SECONDARY);
-}
-
-NMIP4Config *
-nm_ip4_config_clone(const NMIP4Config *self)
-{
- NMIP4Config *copy;
-
- copy = nm_ip4_config_new(nm_ip4_config_get_multi_idx(self), -1);
- nm_ip4_config_replace(copy, self, NULL);
-
- return copy;
-}
-
-NMIP4Config *
-nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex)
-{
- NMIP4Config * self;
- NMIP4ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter iter;
- const NMPObject * plobj = NULL;
-
- nm_assert(ifindex > 0);
-
- /* Slaves have no IP configuration */
- if (nm_platform_link_get_master(platform, ifindex) > 0)
- return NULL;
-
- self = nm_ip4_config_new(multi_idx, ifindex);
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex);
- if (head_entry) {
- nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
- if (!_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_addresses_,
- ifindex,
- plobj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- nm_assert_not_reached();
- }
- head_entry = nm_ip4_config_lookup_addresses(self);
- nm_assert(head_entry);
- nm_dedup_multi_head_entry_sort(head_entry, sort_captured_addresses, NULL);
- _notify_addresses(self);
- }
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ROUTE, ifindex);
-
- /* Extract gateway from default route */
- nmp_cache_iter_for_each (&iter, head_entry, &plobj)
- _add_route(self, plobj, NULL, NULL);
-
- return self;
-}
-
-void
-nm_ip4_config_update_routes_metric(NMIP4Config *self, gint64 metric)
-{
- gs_free NMPlatformIP4Route *routes = NULL;
- gboolean need_update = FALSE;
- const NMPlatformIP4Route * r;
- NMDedupMultiIter iter;
- guint num = 0, i = 0;
-
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- if (r->metric != metric)
- need_update = TRUE;
- num++;
- }
- if (!need_update)
- return;
-
- routes = g_new(NMPlatformIP4Route, num);
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- routes[i] = *r;
- routes[i].metric = metric;
- i++;
- }
-
- g_object_freeze_notify(G_OBJECT(self));
- nm_ip4_config_reset_routes(self);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_route(self, &routes[i], NULL);
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-void
-nm_ip4_config_add_dependent_routes(NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf,
- GPtrArray ** out_ip4_dev_route_blacklist)
-{
- GPtrArray * ip4_dev_route_blacklist = NULL;
- const NMPlatformIP4Address *my_addr;
- const NMPlatformIP4Route * my_route;
- int ifindex;
- NMDedupMultiIter iter;
-
- g_return_if_fail(NM_IS_IP4_CONFIG(self));
-
- ifindex = nm_ip4_config_get_ifindex(self);
- g_return_if_fail(ifindex > 0);
-
- /* For IPv6 slaac, we explicitly add the device-routes (onlink) to NMIP6Config.
- * As we don't do that for IPv4 (and manual IPv6 addresses), add them explicitly. */
-
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &my_addr) {
- nm_auto_nmpobj NMPObject *r = NULL;
- NMPlatformIP4Route * route;
- in_addr_t network;
-
- if (my_addr->plen == 0)
- continue;
-
- nm_assert(my_addr->plen <= 32);
-
- /* The destination network depends on the peer-address. */
- network = nm_utils_ip4_address_clear_host_address(my_addr->peer_address, my_addr->plen);
-
- if (my_addr->external)
- continue;
-
- if (nm_utils_ip4_address_is_zeronet(network)) {
- /* Kernel doesn't add device-routes for destinations that
- * start with 0.x.y.z. Skip them. */
- continue;
- }
-
- if (my_addr->plen == 32 && my_addr->address == my_addr->peer_address) {
- /* Kernel doesn't add device-routes for /32 addresses unless
- * they have a peer. */
- continue;
- }
-
- r = nmp_object_new(NMP_OBJECT_TYPE_IP4_ROUTE, NULL);
- route = NMP_OBJECT_CAST_IP4_ROUTE(r);
-
- route->ifindex = ifindex;
- route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- route->network = network;
- route->plen = my_addr->plen;
- route->pref_src = my_addr->address;
- route->table_coerced = nm_platform_route_table_coerce(route_table);
- route->metric = route_metric;
- route->scope_inv = nm_platform_route_scope_inv(NM_RT_SCOPE_LINK);
-
- nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we already track this route. Don't add it again. */
- } else
- _add_route(self, r, NULL, NULL);
-
- if (out_ip4_dev_route_blacklist
- && (route_table != RT_TABLE_MAIN
- || route_metric != NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE)) {
- nm_auto_nmpobj NMPObject *r_dev = NULL;
-
- r_dev = nmp_object_clone(r, FALSE);
- route = NMP_OBJECT_CAST_IP4_ROUTE(r_dev);
- route->table_coerced = nm_platform_route_table_coerce(RT_TABLE_MAIN);
- route->metric = NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE;
-
- nm_platform_ip_route_normalize(AF_INET, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r_dev, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we track such a route explicitly. Don't blacklist it. */
- } else {
- if (!ip4_dev_route_blacklist)
- ip4_dev_route_blacklist =
- g_ptr_array_new_with_free_func((GDestroyNotify) nmp_object_unref);
-
- g_ptr_array_add(ip4_dev_route_blacklist, g_steal_pointer(&r_dev));
- }
- }
- }
-
-again:
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &my_route) {
- NMPlatformIP4Route rt;
-
- if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route) || my_route->gateway == 0
- || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rt_source)
- || nm_ip4_config_get_direct_route_for_host(
- self,
- my_route->gateway,
- nm_platform_route_table_uncoerce(my_route->table_coerced, TRUE)))
- continue;
-
- rt = *my_route;
- rt.network = my_route->gateway;
- rt.plen = 32;
- rt.gateway = 0;
- _add_route(self, NULL, &rt, NULL);
- /* adding the route might have invalidated the iteration. Start again. */
- goto again;
- }
-
- NM_SET_OUT(out_ip4_dev_route_blacklist, ip4_dev_route_blacklist);
-}
-
-gboolean
-nm_ip4_config_commit(const NMIP4Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync)
-{
- gs_unref_ptrarray GPtrArray *addresses = NULL;
- gs_unref_ptrarray GPtrArray *routes = NULL;
- gs_unref_ptrarray GPtrArray *routes_prune = NULL;
- int ifindex;
- gboolean success = TRUE;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
-
- ifindex = nm_ip4_config_get_ifindex(self);
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- addresses =
- nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_addresses(self), NULL, NULL);
-
- routes = nm_dedup_multi_objs_to_ptr_array_head(nm_ip4_config_lookup_routes(self), NULL, NULL);
-
- routes_prune =
- nm_platform_ip_route_get_prune_list(platform, AF_INET, ifindex, route_table_sync);
-
- nm_platform_ip4_address_sync(platform, ifindex, addresses);
-
- if (!nm_platform_ip_route_sync(platform, AF_INET, ifindex, routes, routes_prune, NULL))
- success = FALSE;
-
- return success;
-}
-
-void
-nm_ip4_config_merge_setting(NMIP4Config * self,
- NMSettingIPConfig * setting,
- NMSettingConnectionMdns mdns,
- NMSettingConnectionLlmnr llmnr,
- guint32 route_table,
- guint32 route_metric)
-{
- guint naddresses, nroutes, nnameservers, nsearches;
- int i, priority;
- const char *gateway_str;
- guint32 gateway_bin;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_IP4_CONFIG(setting));
-
- g_object_freeze_notify(G_OBJECT(self));
-
- naddresses = nm_setting_ip_config_get_num_addresses(setting);
- nroutes = nm_setting_ip_config_get_num_routes(setting);
- nnameservers = nm_setting_ip_config_get_num_dns(setting);
- nsearches = nm_setting_ip_config_get_num_dns_searches(setting);
-
- /* Gateway */
- if (!nm_setting_ip_config_get_never_default(setting)
- && (gateway_str = nm_setting_ip_config_get_gateway(setting))
- && inet_pton(AF_INET, gateway_str, &gateway_bin) == 1 && gateway_bin) {
- const NMPlatformIP4Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_USER,
- .gateway = gateway_bin,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
-
- _add_route(self, NULL, &r, NULL);
- }
-
- /* Addresses */
- for (i = 0; i < naddresses; i++) {
- NMIPAddress * s_addr = nm_setting_ip_config_get_address(setting, i);
- GVariant * label;
- NMPlatformIP4Address address;
-
- memset(&address, 0, sizeof(address));
- nm_ip_address_get_address_binary(s_addr, &address.address);
- address.peer_address = address.address;
- address.plen = nm_ip_address_get_prefix(s_addr);
- nm_assert(address.plen <= 32);
- address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
- address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
- address.addr_source = NM_IP_CONFIG_SOURCE_USER;
-
- label = nm_ip_address_get_attribute(s_addr, NM_IP_ADDRESS_ATTRIBUTE_LABEL);
- if (label)
- g_strlcpy(address.label, g_variant_get_string(label, NULL), sizeof(address.label));
-
- _add_address(self, NULL, &address);
- }
-
- /* Routes */
- for (i = 0; i < nroutes; i++) {
- NMIPRoute * s_route = nm_setting_ip_config_get_route(setting, i);
- NMPlatformIP4Route route;
- gint64 m;
-
- if (nm_ip_route_get_family(s_route) != AF_INET) {
- nm_assert_not_reached();
- continue;
- }
-
- memset(&route, 0, sizeof(route));
- nm_ip_route_get_dest_binary(s_route, &route.network);
-
- route.plen = nm_ip_route_get_prefix(s_route);
- nm_assert(route.plen <= 32);
-
- nm_ip_route_get_next_hop_binary(s_route, &route.gateway);
- m = nm_ip_route_get_metric(s_route);
- if (m < 0)
- route.metric = route_metric;
- else
- route.metric = m;
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
-
- route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
-
- nm_utils_ip_route_attribute_to_platform(AF_INET,
- s_route,
- NM_PLATFORM_IP_ROUTE_CAST(&route),
- route_table);
- _add_route(self, NULL, &route, NULL);
- }
-
- /* DNS */
- if (nm_setting_ip_config_get_ignore_auto_dns(setting)) {
- nm_ip4_config_reset_nameservers(self);
- nm_ip4_config_reset_domains(self);
- nm_ip4_config_reset_searches(self);
- }
- for (i = 0; i < nnameservers; i++) {
- guint32 ip;
-
- if (inet_pton(AF_INET, nm_setting_ip_config_get_dns(setting, i), &ip) == 1)
- nm_ip4_config_add_nameserver(self, ip);
- }
- for (i = 0; i < nsearches; i++)
- nm_ip4_config_add_search(self, nm_setting_ip_config_get_dns_search(setting, i));
-
- i = 0;
- while ((i = nm_setting_ip_config_next_valid_dns_option(setting, i)) >= 0) {
- nm_ip4_config_add_dns_option(self, nm_setting_ip_config_get_dns_option(setting, i));
- i++;
- }
-
- priority = nm_setting_ip_config_get_dns_priority(setting);
- if (priority)
- nm_ip4_config_set_dns_priority(self, priority);
-
- nm_ip4_config_mdns_set(self, mdns);
- nm_ip4_config_llmnr_set(self, llmnr);
-
- nm_ip4_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting));
-
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-NMSetting *
-nm_ip4_config_create_setting(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate * priv;
- NMSettingIPConfig * s_ip4;
- guint nnameservers, nsearches, noptions;
- const char * method = NULL;
- int i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- const NMPlatformIP4Route * route;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- s_ip4 = NM_SETTING_IP_CONFIG(nm_setting_ip4_config_new());
-
- if (!self) {
- g_object_set(s_ip4,
- NM_SETTING_IP_CONFIG_METHOD,
- NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
- NULL);
- return NM_SETTING(s_ip4);
- }
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nnameservers = nm_ip4_config_get_num_nameservers(self);
- nsearches = nm_ip4_config_get_num_searches(self);
- noptions = nm_ip4_config_get_num_dns_options(self);
-
- /* Addresses */
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
- NMIPAddress *s_addr;
-
- /* Detect dynamic address */
- if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
- method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
- continue;
- }
-
- /* Static address found. */
- if (!method)
- method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
-
- s_addr = nm_ip_address_new_binary(AF_INET, &address->address, address->plen, NULL);
- if (*address->label)
- nm_ip_address_set_attribute(s_addr,
- NM_IP_ADDRESS_ATTRIBUTE_LABEL,
- g_variant_new_string(address->label));
-
- nm_setting_ip_config_add_address(s_ip4, s_addr);
- nm_ip_address_unref(s_addr);
- }
-
- /* Gateway */
- if (priv->best_default_route && nm_setting_ip_config_get_num_addresses(s_ip4) > 0) {
- g_object_set(
- s_ip4,
- NM_SETTING_IP_CONFIG_GATEWAY,
- _nm_utils_inet4_ntop(NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway,
- sbuf),
- NULL);
- }
-
- /* Use 'disabled' if the method wasn't previously set */
- if (!method)
- method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED;
-
- g_object_set(s_ip4, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
-
- /* Routes */
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
- NMIPRoute *s_route;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
- continue;
-
- /* Ignore routes provided by external sources */
- if (route->rt_source
- != nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER))
- continue;
-
- s_route = nm_ip_route_new_binary(AF_INET,
- &route->network,
- route->plen,
- &route->gateway,
- route->metric,
- NULL);
- nm_setting_ip_config_add_route(s_ip4, s_route);
- nm_ip_route_unref(s_route);
- }
-
- /* DNS */
- for (i = 0; i < nnameservers; i++) {
- guint32 nameserver = nm_ip4_config_get_nameserver(self, i);
-
- nm_setting_ip_config_add_dns(s_ip4, _nm_utils_inet4_ntop(nameserver, sbuf));
- }
- for (i = 0; i < nsearches; i++) {
- const char *search = nm_ip4_config_get_search(self, i);
-
- nm_setting_ip_config_add_dns_search(s_ip4, search);
- }
-
- for (i = 0; i < noptions; i++) {
- const char *option = nm_ip4_config_get_dns_option(self, i);
-
- nm_setting_ip_config_add_dns_option(s_ip4, option);
- }
-
- g_object_set(s_ip4,
- NM_SETTING_IP_CONFIG_DNS_PRIORITY,
- nm_ip4_config_get_dns_priority(self),
- NULL);
-
- return NM_SETTING(s_ip4);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_merge(NMIP4Config * dst,
- const NMIP4Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- guint32 i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address = NULL;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &address) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) && !address->external) {
- NMPlatformIP4Address a;
-
- a = *address;
- a.external = TRUE;
- _add_address(dst, NULL, &a);
- } else
- _add_address(dst, NMP_OBJECT_UP_CAST(address), NULL);
- }
-
- /* nameservers */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++)
- nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
- }
-
- /* routes */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- const NMPlatformIP4Route *r_src;
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r_src) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
- && !NM_FLAGS_HAS(src_priv->config_flags,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
- continue;
- if (default_route_metric_penalty) {
- NMPlatformIP4Route r = *r_src;
-
- r.metric =
- nm_utils_ip_route_metric_penalize(r.metric, default_route_metric_penalty);
- _add_route(dst, NULL, &r, NULL);
- continue;
- }
- }
- _add_route(dst, ipconf_iter.current->obj, NULL, NULL);
- }
- }
-
- /* domains */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_domains(src); i++)
- nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
- }
-
- /* dns searches */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_searches(src); i++)
- nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
- }
-
- /* dns options */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++)
- nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
- }
-
- /* MTU */
- if (src_priv->mtu_source > dst_priv->mtu_source
- || (src_priv->mtu_source == dst_priv->mtu_source
- && ((!dst_priv->mtu && src_priv->mtu)
- || (dst_priv->mtu && src_priv->mtu < dst_priv->mtu))))
- nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
-
- /* NIS */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++)
- nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
-
- if (nm_ip4_config_get_nis_domain(src))
- nm_ip4_config_set_nis_domain(dst, nm_ip4_config_get_nis_domain(src));
- }
-
- /* WINS */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip4_config_get_num_wins(src); i++)
- nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
- }
-
- /* metered flag */
- nm_ip4_config_set_metered(dst,
- nm_ip4_config_get_metered(dst) || nm_ip4_config_get_metered(src));
-
- /* never default */
- nm_ip4_config_set_never_default(dst,
- nm_ip4_config_get_never_default(dst)
- || nm_ip4_config_get_never_default(src));
-
- /* DNS priority */
- if (nm_ip4_config_get_dns_priority(src))
- nm_ip4_config_set_dns_priority(dst, nm_ip4_config_get_dns_priority(src));
-
- /* mdns */
- nm_ip4_config_mdns_set(dst, NM_MAX(nm_ip4_config_mdns_get(src), nm_ip4_config_mdns_get(dst)));
- /* LLMNR */
- nm_ip4_config_llmnr_set(dst,
- NM_MAX(nm_ip4_config_llmnr_get(src), nm_ip4_config_llmnr_get(dst)));
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-/*****************************************************************************/
-
-static int
-_nameservers_get_index(const NMIP4Config *self, guint32 ns)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nameservers->len; i++) {
- guint32 n = g_array_index(priv->nameservers, guint32, i);
-
- if (ns == n)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_domains_get_index(const NMIP4Config *self, const char *domain)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->domains->len; i++) {
- const char *d = g_ptr_array_index(priv->domains, i);
-
- if (g_strcmp0(domain, d) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_searches_get_index(const NMIP4Config *self, const char *search)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->searches->len; i++) {
- const char *s = g_ptr_array_index(priv->searches, i);
-
- if (g_strcmp0(search, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_dns_options_get_index(const NMIP4Config *self, const char *option)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->dns_options->len; i++) {
- const char *s = g_ptr_array_index(priv->dns_options, i);
-
- if (g_strcmp0(option, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_nis_servers_get_index(const NMIP4Config *self, guint32 nis_server)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nis->len; i++) {
- guint32 n = g_array_index(priv->nis, guint32, i);
-
- if (n == nis_server)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_wins_get_index(const NMIP4Config *self, guint32 wins_server)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->wins->len; i++) {
- guint32 n = g_array_index(priv->wins, guint32, i);
-
- if (n == wins_server)
- return (int) i;
- }
- return -1;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_ip4_config_subtract:
- * @dst: config from which to remove everything in @src
- * @src: config to remove from @dst
- * @default_route_metric_penalty: pretend that on source we applied
- * a route penalty on the default-route. It means, for default routes
- * we don't remove routes that match exactly, but those with a lower
- * metric (with the penalty removed).
- *
- * Removes everything in @src from @dst.
- */
-void
-nm_ip4_config_subtract(NMIP4Config * dst,
- const NMIP4Config *src,
- guint32 default_route_metric_penalty)
-{
- NMIP4ConfigPrivate * dst_priv;
- guint i;
- int idx;
- const NMPlatformIP4Address *a;
- const NMPlatformIP4Route * r;
- NMDedupMultiIter ipconf_iter;
- gboolean changed;
- gboolean changed_default_route;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- changed = FALSE;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, src, &a) {
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses,
- NMP_OBJECT_UP_CAST(a),
- NULL))
- changed = TRUE;
- }
- if (changed)
- _notify_addresses(dst);
-
- /* nameservers */
- for (i = 0; i < nm_ip4_config_get_num_nameservers(src); i++) {
- idx = _nameservers_get_index(dst, nm_ip4_config_get_nameserver(src, i));
- if (idx >= 0)
- nm_ip4_config_del_nameserver(dst, idx);
- }
-
- /* routes */
- changed = FALSE;
- changed_default_route = FALSE;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, src, &r) {
- const NMPObject * o_src = NMP_OBJECT_UP_CAST(r);
- NMPObject o_lookup_copy;
- const NMPObject * o_lookup;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP4Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When subtracting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_src);
- rr = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_src;
-
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes,
- o_lookup,
- (gconstpointer *) &obj_old)) {
- if (dst_priv->best_default_route == obj_old) {
- nm_clear_nmp_object(&dst_priv->best_default_route);
- changed_default_route = TRUE;
- }
- changed = TRUE;
- }
- }
- if (changed_default_route) {
- nmp_object_ref_set(&dst_priv->best_default_route,
- _nm_ip4_config_best_default_route_find(dst));
- _notify(dst, PROP_GATEWAY);
- }
- if (changed)
- _notify_routes(dst);
-
- /* domains */
- for (i = 0; i < nm_ip4_config_get_num_domains(src); i++) {
- idx = _domains_get_index(dst, nm_ip4_config_get_domain(src, i));
- if (idx >= 0)
- nm_ip4_config_del_domain(dst, idx);
- }
-
- /* dns searches */
- for (i = 0; i < nm_ip4_config_get_num_searches(src); i++) {
- idx = _searches_get_index(dst, nm_ip4_config_get_search(src, i));
- if (idx >= 0)
- nm_ip4_config_del_search(dst, idx);
- }
-
- /* dns options */
- for (i = 0; i < nm_ip4_config_get_num_dns_options(src); i++) {
- idx = _dns_options_get_index(dst, nm_ip4_config_get_dns_option(src, i));
- if (idx >= 0)
- nm_ip4_config_del_dns_option(dst, idx);
- }
-
- /* MTU */
- if (nm_ip4_config_get_mtu(src) == nm_ip4_config_get_mtu(dst)
- && nm_ip4_config_get_mtu_source(src) == nm_ip4_config_get_mtu_source(dst))
- nm_ip4_config_set_mtu(dst, 0, NM_IP_CONFIG_SOURCE_UNKNOWN);
-
- /* NIS */
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(src); i++) {
- idx = _nis_servers_get_index(dst, nm_ip4_config_get_nis_server(src, i));
- if (idx >= 0)
- nm_ip4_config_del_nis_server(dst, idx);
- }
-
- if (g_strcmp0(nm_ip4_config_get_nis_domain(src), nm_ip4_config_get_nis_domain(dst)) == 0)
- nm_ip4_config_set_nis_domain(dst, NULL);
-
- /* WINS */
- for (i = 0; i < nm_ip4_config_get_num_wins(src); i++) {
- idx = _wins_get_index(dst, nm_ip4_config_get_wins(src, i));
- if (idx >= 0)
- nm_ip4_config_del_wins(dst, idx);
- }
-
- /* DNS priority */
- if (nm_ip4_config_get_dns_priority(src) == nm_ip4_config_get_dns_priority(dst))
- nm_ip4_config_set_dns_priority(dst, 0);
-
- /* mdns */
- if (nm_ip4_config_mdns_get(src) == nm_ip4_config_mdns_get(dst))
- nm_ip4_config_mdns_set(dst, NM_SETTING_CONNECTION_MDNS_DEFAULT);
-
- /* LLMNR */
- if (nm_ip4_config_llmnr_get(src) == nm_ip4_config_llmnr_get(dst))
- nm_ip4_config_llmnr_set(dst, NM_SETTING_CONNECTION_LLMNR_DEFAULT);
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-static gboolean
-_nm_ip4_config_intersect_helper(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty,
- gboolean update_dst)
-{
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *a;
- const NMPlatformIP4Route * r;
- const NMPObject * new_best_default_route;
- gboolean changed, result = FALSE;
-
- g_return_val_if_fail(src, FALSE);
- g_return_val_if_fail(dst, FALSE);
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- if (update_dst)
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- if (intersect_addresses) {
- changed = FALSE;
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, dst, &a) {
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip4_addresses,
- NMP_OBJECT_UP_CAST(a)))
- continue;
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (changed) {
- _notify_addresses(dst);
- result = TRUE;
- }
- }
-
- /* ignore nameservers */
-
- /* routes */
- if (!intersect_routes)
- goto skip_routes;
-
- changed = FALSE;
- new_best_default_route = NULL;
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, dst, &r) {
- const NMPObject *o_dst = NMP_OBJECT_UP_CAST(r);
- const NMPObject *o_lookup;
- NMPObject o_lookup_copy;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP4Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When intersecting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_dst);
- rr = NMP_OBJECT_CAST_IP4_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_dst;
-
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip4_routes,
- o_lookup)) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, o_dst);
- continue;
- }
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route)) {
- nm_assert(changed);
- _notify(dst, PROP_GATEWAY);
- }
-
- if (changed) {
- _notify_routes(dst);
- result = TRUE;
- }
-
-skip_routes:
- /* ignore domains */
- /* ignore dns searches */
- /* ignore dns options */
- /* ignore NIS */
- /* ignore WINS */
- /* ignore mdns */
- /* ignore LLMNR */
-
- if (update_dst)
- g_object_thaw_notify(G_OBJECT(dst));
- return result;
-}
-
-/**
- * nm_ip4_config_intersect:
- * @dst: a configuration to be updated
- * @src: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @src and @dst and updates @dst in place
- * with the result.
- */
-void
-nm_ip4_config_intersect(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _nm_ip4_config_intersect_helper(dst,
- src,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
-}
-
-/**
- * nm_ip4_config_intersect_alloc:
- * @a: a configuration
- * @b: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @a and @b and returns the result in a newly
- * allocated configuration. As a special case, if @a and @b are identical (with
- * respect to the only properties considered - addresses and routes) the
- * functions returns NULL so that one of existing configuration can be reused
- * without allocation.
- *
- * Returns: the intersection between @a and @b, or %NULL if the result is equal
- * to @a and @b.
- */
-NMIP4Config *
-nm_ip4_config_intersect_alloc(const NMIP4Config *a,
- const NMIP4Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- NMIP4Config *a_copy;
-
- if (_nm_ip4_config_intersect_helper((NMIP4Config *) a,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- FALSE)) {
- a_copy = nm_ip4_config_clone(a);
- _nm_ip4_config_intersect_helper(a_copy,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
- return a_copy;
- } else
- return NULL;
-}
-
-/**
- * nm_ip4_config_replace:
- * @dst: config to replace with @src content
- * @src: source config to copy
- * @relevant_changes: return whether there are changes to the
- * destination object that are relevant. This is equal to
- * nm_ip4_config_equal() showing any difference.
- *
- * Replaces everything in @dst with @src so that the two configurations
- * contain the same content -- with the exception of the dbus path.
- *
- * Returns: whether the @dst instance changed in any way (including minor changes,
- * that are not signaled by the output parameter @relevant_changes).
- */
-gboolean
-nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes)
-{
-#if NM_MORE_ASSERTS
- gboolean config_equal;
-#endif
- gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
- guint i, num;
- NMIP4ConfigPrivate * dst_priv;
- const NMIP4ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
- const NMDedupMultiHeadEntry *head_entry_src;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(src != NULL, FALSE);
- g_return_val_if_fail(dst != NULL, FALSE);
- g_return_val_if_fail(src != dst, FALSE);
-
-#if NM_MORE_ASSERTS
- config_equal = nm_ip4_config_equal(dst, src);
-#endif
-
- dst_priv = NM_IP4_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP4_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* ifindex */
- if (src_priv->ifindex != dst_priv->ifindex) {
- dst_priv->ifindex = src_priv->ifindex;
- has_minor_changes = TRUE;
- }
-
- /* addresses */
- head_entry_src = nm_ip4_config_lookup_addresses(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip4_address_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP4Address *r_src = NULL;
- const NMPlatformIP4Address *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip4_address(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip4_address_cmp(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->address != r_dst->address || r_src->plen != r_dst->plen
- || r_src->peer_address != r_dst->peer_address) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_addresses);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses_,
- dst_priv->ifindex,
- ipconf_iter_src.current->obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip4_addresses,
- FALSE);
- _notify_addresses(dst);
- }
-
- /* routes */
- head_entry_src = nm_ip4_config_lookup_routes(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip4_route_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP4Route *r_src = NULL;
- const NMPlatformIP4Route *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip4_route(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip4_route_cmp_full(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->plen != r_dst->plen
- || !nm_utils_ip4_address_same_prefix(r_src->network, r_dst->network, r_src->plen)
- || r_src->gateway != r_dst->gateway || r_src->metric != r_dst->metric) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- new_best_default_route = NULL;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip4_routes);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- const NMPObject *o = ipconf_iter_src.current->obj;
- const NMPObject *obj_new;
-
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes_,
- dst_priv->ifindex,
- o,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new);
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip4_routes,
- FALSE);
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route))
- _notify(dst, PROP_GATEWAY);
- _notify_routes(dst);
- }
-
- /* nameservers */
- num = nm_ip4_config_get_num_nameservers(src);
- are_equal = num == nm_ip4_config_get_num_nameservers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_nameserver(src, i) != nm_ip4_config_get_nameserver(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_nameservers(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_nameserver(dst, nm_ip4_config_get_nameserver(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* domains */
- num = nm_ip4_config_get_num_domains(src);
- are_equal = num == nm_ip4_config_get_num_domains(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_domain(src, i), nm_ip4_config_get_domain(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_domains(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_domain(dst, nm_ip4_config_get_domain(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns searches */
- num = nm_ip4_config_get_num_searches(src);
- are_equal = num == nm_ip4_config_get_num_searches(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_search(src, i), nm_ip4_config_get_search(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_searches(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_search(dst, nm_ip4_config_get_search(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns options */
- num = nm_ip4_config_get_num_dns_options(src);
- are_equal = num == nm_ip4_config_get_num_dns_options(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip4_config_get_dns_option(src, i),
- nm_ip4_config_get_dns_option(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_dns_options(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_dns_option(dst, nm_ip4_config_get_dns_option(src, i));
- has_relevant_changes = TRUE;
- }
-
- if (src_priv->mdns != dst_priv->mdns) {
- dst_priv->mdns = src_priv->mdns;
- has_relevant_changes = TRUE;
- }
-
- if (src_priv->llmnr != dst_priv->llmnr) {
- dst_priv->llmnr = src_priv->llmnr;
- has_relevant_changes = TRUE;
- }
-
- /* DNS priority */
- if (src_priv->dns_priority != dst_priv->dns_priority) {
- nm_ip4_config_set_dns_priority(dst, src_priv->dns_priority);
- has_minor_changes = TRUE;
- }
-
- /* nis */
- num = nm_ip4_config_get_num_nis_servers(src);
- are_equal = num == nm_ip4_config_get_num_nis_servers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_nis_server(src, i) != nm_ip4_config_get_nis_server(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_nis_servers(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_nis_server(dst, nm_ip4_config_get_nis_server(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* nis_domain */
- if (g_strcmp0(src_priv->nis_domain, dst_priv->nis_domain)) {
- nm_ip4_config_set_nis_domain(dst, src_priv->nis_domain);
- has_relevant_changes = TRUE;
- }
-
- /* wins */
- num = nm_ip4_config_get_num_wins(src);
- are_equal = num == nm_ip4_config_get_num_wins(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (nm_ip4_config_get_wins(src, i) != nm_ip4_config_get_wins(dst, i)) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip4_config_reset_wins(dst);
- for (i = 0; i < num; i++)
- nm_ip4_config_add_wins(dst, nm_ip4_config_get_wins(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* mtu */
- if (src_priv->mtu != dst_priv->mtu || src_priv->mtu_source != dst_priv->mtu_source) {
- nm_ip4_config_set_mtu(dst, src_priv->mtu, src_priv->mtu_source);
- has_minor_changes = TRUE;
- }
-
- /* metered */
- if (src_priv->metered != dst_priv->metered) {
- dst_priv->metered = src_priv->metered;
- has_minor_changes = TRUE;
- }
-
- /* never default */
- if (src_priv->never_default != dst_priv->never_default) {
- dst_priv->never_default = src_priv->never_default;
- has_minor_changes = TRUE;
- }
-
-#if NM_MORE_ASSERTS
- /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
- * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
- nm_assert(config_equal == !has_relevant_changes);
-#endif
-
- g_object_thaw_notify(G_OBJECT(dst));
-
- if (relevant_changes)
- *relevant_changes = has_relevant_changes;
-
- return has_relevant_changes || has_minor_changes;
-}
-
-void
-nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, NMLogDomain domain)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *addr4;
- const NMPlatformIP6Address *addr6;
- const NMPlatformIP4Route * route4;
- const NMPlatformIP6Route * route6;
- const NMIP4Config * ip4;
- const NMIP6Config * ip6;
- int addr_family = AF_UNSPEC;
- char addr_family_char = '?';
- const char * path;
- gconstpointer ptr;
- guint i;
-
- if (self) {
- addr_family = nm_ip_config_get_addr_family(self);
- addr_family_char = nm_utils_addr_family_to_char(addr_family);
- }
-
- nm_log(level, domain, NULL, NULL, "---- NMIP%cConfig %p (%s)", addr_family_char, self, detail);
-
- if (!self)
- return;
-
- path = nm_dbus_object_get_path(NM_DBUS_OBJECT(self));
- if (path)
- nm_log(level, domain, NULL, NULL, " path : %s", path);
-
- if (addr_family == AF_INET) {
- ip4 = NM_IP4_CONFIG(self);
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr4) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " address : %s",
- nm_platform_ip4_address_to_string(addr4, NULL, 0));
- }
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route4) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " route : %s",
- nm_platform_ip4_route_to_string(route4, NULL, 0));
- }
- } else {
- ip6 = NM_IP6_CONFIG(self);
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr6) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " address : %s",
- nm_platform_ip6_address_to_string(addr6, NULL, 0));
- }
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route6) {
- nm_log(level,
- domain,
- NULL,
- NULL,
- " route : %s",
- nm_platform_ip6_route_to_string(route6, NULL, 0));
- }
- }
-
- for (i = 0; i < nm_ip_config_get_num_nameservers(self); i++) {
- char buf[NM_UTILS_INET_ADDRSTRLEN];
-
- ptr = nm_ip_config_get_nameserver(self, i);
- nm_log(level,
- domain,
- NULL,
- NULL,
- " dns : %s",
- nm_utils_inet_ntop(addr_family, ptr, buf));
- }
-
- for (i = 0; i < nm_ip_config_get_num_domains(self); i++)
- nm_log(level, domain, NULL, NULL, " domain : %s", nm_ip_config_get_domain(self, i));
-
- for (i = 0; i < nm_ip_config_get_num_searches(self); i++)
- nm_log(level, domain, NULL, NULL, " search : %s", nm_ip_config_get_search(self, i));
-
- for (i = 0; i < nm_ip_config_get_num_dns_options(self); i++)
- nm_log(level, domain, NULL, NULL, "dns-option: %s", nm_ip_config_get_dns_option(self, i));
-
- nm_log(level, domain, NULL, NULL, " dns-prio : %d", nm_ip_config_get_dns_priority(self));
-
- if (addr_family == AF_INET) {
- ip4 = NM_IP4_CONFIG(self);
- nm_log(level,
- domain,
- NULL,
- NULL,
- " mtu : %" G_GUINT32_FORMAT " (source: %d)",
- nm_ip4_config_get_mtu(ip4),
- (int) nm_ip4_config_get_mtu_source(ip4));
- nm_log(level, domain, NULL, NULL, " metered : %d", (int) nm_ip4_config_get_metered(ip4));
- }
-}
-
-/*****************************************************************************/
-
-gconstpointer
-nm_ip_config_find_first_address(const NMIPConfig *self, NMPlatformMatchFlags match_flag)
-{
- NMDedupMultiIter iter;
- const NMPlatformIPAddress *address;
-
- g_return_val_if_fail(NM_IS_IP_CONFIG(self), NULL);
-
- nm_assert(!NM_FLAGS_ANY(
- match_flag,
- ~(NM_PLATFORM_MATCH_WITH_ADDRTYPE__ANY | NM_PLATFORM_MATCH_WITH_ADDRSTATE__ANY)));
-
- nm_ip_config_iter_ip_address_for_each (&iter, self, &address) {
- if (nm_platform_ip_address_match(nm_ip_config_get_addr_family(self), address, match_flag))
- return address;
- }
-
- return NULL;
-}
-
-void
-nm_ip4_config_reset_addresses(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses) > 0)
- _notify_addresses(self);
-}
-
-static void
-_add_address(NMIP4Config *self, const NMPObject *obj_new, const NMPlatformIP4Address *new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_addresses_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- NULL,
- NULL))
- _notify_addresses(self);
-}
-
-/**
- * nm_ip4_config_add_address:
- * @self: the #NMIP4Config
- * @new: the new address to add to @self
- *
- * Adds the new address to @self. If an address with the same basic properties
- * (address, prefix) already exists in @self, it is overwritten with the
- * lifetime and preferred of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip4_config_add_address(NMIP4Config *self, const NMPlatformIP4Address *new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 32);
- g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_address(self, NULL, new);
-}
-
-void
-_nmtst_ip4_config_del_address(NMIP4Config *self, guint i)
-{
- const NMPlatformIP4Address *a;
-
- a = _nmtst_ip4_config_get_address(self, i);
- if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(a)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip4_config_get_num_addresses(const NMIP4Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip4_config_lookup_addresses(self);
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP4Address *
-nm_ip4_config_get_first_address(const NMIP4Config *self)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP4Address *a = NULL;
-
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &a)
- return a;
- return NULL;
-}
-
-const NMPlatformIP4Address *
-_nmtst_ip4_config_get_address(const NMIP4Config *self, guint i)
-{
- NMDedupMultiIter iter = {};
- const NMPlatformIP4Address *a = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip4_address_for_each (&iter, self, &a) {
- if (i == j)
- return a;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-gboolean
-nm_ip4_config_address_exists(const NMIP4Config *self, const NMPlatformIP4Address *needle)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- NMPObject obj_stack;
-
- nmp_object_stackinit_id_ip4_address(&obj_stack,
- priv->ifindex,
- needle->address,
- needle->plen,
- needle->peer_address);
- return !!nm_dedup_multi_index_lookup_obj(priv->multi_idx, &priv->idx_ip4_addresses, &obj_stack);
-}
-
-/*****************************************************************************/
-
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP4Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type)
-{
- const NMIP4ConfigPrivate *priv;
-
- nm_assert(NM_IS_IP4_CONFIG(self));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP4_ROUTE);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return _nm_ip_config_lookup_ip_route(priv->multi_idx, &priv->idx_ip4_routes_, needle, cmp_type);
-}
-
-void
-nm_ip4_config_reset_routes(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes) > 0) {
- if (nm_clear_nmp_object(&priv->best_default_route))
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- }
-}
-
-static void
-_add_route(NMIP4Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new)
-{
- NMIP4ConfigPrivate * priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- const NMPObject * obj_new_2;
-
- nm_assert((!new) != (!obj_new));
- nm_assert(!new || _route_valid(new));
- nm_assert(!obj_new || _route_valid(NMP_OBJECT_CAST_IP4_ROUTE(obj_new)));
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip4_routes_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- &obj_old,
- &obj_new_2)) {
- gboolean changed_default_route = FALSE;
-
- if (priv->best_default_route == obj_old && obj_old != obj_new_2) {
- changed_default_route = TRUE;
- nm_clear_nmp_object(&priv->best_default_route);
- }
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
- if (_nm_ip_config_best_default_route_merge(&priv->best_default_route, obj_new_2))
- changed_default_route = TRUE;
-
- if (changed_default_route)
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- } else
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
-}
-
-/**
- * nm_ip4_config_add_route:
- * @self: the #NMIP4Config
- * @new: the new route to add to @self
- * @out_obj_new: (allow-none) (out): the added route object. Must be unrefed
- * by caller.
- *
- * Adds the new route to @self. If a route with the same basic properties
- * (network, prefix) already exists in @self, it is overwritten including the
- * gateway and metric of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip4_config_add_route(NMIP4Config *self,
- const NMPlatformIP4Route *new,
- const NMPObject **out_obj_new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 32);
- g_return_if_fail(NM_IP4_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_route(self, NULL, new, out_obj_new);
-}
-
-void
-_nmtst_ip4_config_del_route(NMIP4Config *self, guint i)
-{
- const NMPlatformIP4Route *r;
-
- r = _nmtst_ip4_config_get_route(self, i);
- if (!nm_ip4_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(r)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip4_config_get_num_routes(const NMIP4Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip4_config_lookup_routes(self);
- nm_assert(!head_entry || head_entry->len == c_list_length(&head_entry->lst_entries_head));
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP4Route *
-_nmtst_ip4_config_get_route(const NMIP4Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP4Route *r = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip4_route_for_each (&iter, self, &r) {
- if (i == j)
- return r;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP4Route *
-nm_ip4_config_get_direct_route_for_host(const NMIP4Config *self,
- in_addr_t host,
- guint32 route_table)
-{
- const NMPlatformIP4Route *best_route = NULL;
- const NMPlatformIP4Route *item;
- NMDedupMultiIter ipconf_iter;
-
- g_return_val_if_fail(host, NULL);
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &item) {
- if (item->gateway != 0)
- continue;
-
- if (best_route && best_route->plen > item->plen)
- continue;
-
- if (nm_platform_route_table_uncoerce(item->table_coerced, TRUE) != route_table)
- continue;
-
- if (nm_utils_ip4_address_clear_host_address(host, item->plen)
- != nm_utils_ip4_address_clear_host_address(item->network, item->plen))
- continue;
-
- if (best_route && best_route->metric <= item->metric)
- continue;
-
- best_route = item;
- }
- return best_route;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_nameservers(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->nameservers->len != 0) {
- g_array_set_size(priv->nameservers, 0);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
- }
-}
-
-void
-nm_ip4_config_add_nameserver(NMIP4Config *self, guint32 new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != 0);
-
- for (i = 0; i < priv->nameservers->len; i++)
- if (new == g_array_index(priv->nameservers, guint32, i))
- return;
-
- g_array_append_val(priv->nameservers, new);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
-}
-
-void
-nm_ip4_config_del_nameserver(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nameservers->len);
-
- g_array_remove_index(priv->nameservers, i);
- nm_gobject_notify_together(self, PROP_NAMESERVER_DATA, PROP_NAMESERVERS);
-}
-
-guint
-nm_ip4_config_get_num_nameservers(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nameservers->len;
-}
-
-guint32
-nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->nameservers, guint32, i);
-}
-
-const in_addr_t *
-_nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return &g_array_index(priv->nameservers, guint32, i);
-}
-
-/*****************************************************************************/
-
-gboolean
-_nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain)
-{
- char * copy = NULL;
- size_t len;
-
- g_return_val_if_fail(domain, FALSE);
- g_return_val_if_fail(domain[0] != '\0', FALSE);
-
- if (domain[0] == '.' || strstr(domain, ".."))
- return FALSE;
-
- len = strlen(domain);
- if (domain[len - 1] == '.')
- domain = copy = g_strndup(domain, len - 1);
-
- if (nm_strv_ptrarray_find_first(array, domain) >= 0) {
- g_free(copy);
- return FALSE;
- }
-
- g_ptr_array_add(array, copy ?: g_strdup(domain));
- return TRUE;
-}
-
-void
-nm_ip4_config_reset_domains(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->domains->len != 0) {
- g_ptr_array_set_size(priv->domains, 0);
- _notify(self, PROP_DOMAINS);
- }
-}
-
-void
-nm_ip4_config_add_domain(NMIP4Config *self, const char *domain)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->domains, domain))
- _notify(self, PROP_DOMAINS);
-}
-
-void
-nm_ip4_config_del_domain(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->domains->len);
-
- g_ptr_array_remove_index(priv->domains, i);
- _notify(self, PROP_DOMAINS);
-}
-
-guint
-nm_ip4_config_get_num_domains(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->domains->len;
-}
-
-const char *
-nm_ip4_config_get_domain(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->domains, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_searches(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->searches->len != 0) {
- g_ptr_array_set_size(priv->searches, 0);
- _notify(self, PROP_SEARCHES);
- }
-}
-
-void
-nm_ip4_config_add_search(NMIP4Config *self, const char *search)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->searches, search))
- _notify(self, PROP_SEARCHES);
-}
-
-void
-nm_ip4_config_del_search(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->searches->len);
-
- g_ptr_array_remove_index(priv->searches, i);
- _notify(self, PROP_SEARCHES);
-}
-
-guint
-nm_ip4_config_get_num_searches(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->searches->len;
-}
-
-const char *
-nm_ip4_config_get_search(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->searches, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_dns_options(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->dns_options->len != 0) {
- g_ptr_array_set_size(priv->dns_options, 0);
- _notify(self, PROP_DNS_OPTIONS);
- }
-}
-
-void
-nm_ip4_config_add_dns_option(NMIP4Config *self, const char *new)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
- g_return_if_fail(new[0] != '\0');
-
- for (i = 0; i < priv->dns_options->len; i++)
- if (!g_strcmp0(g_ptr_array_index(priv->dns_options, i), new))
- return;
-
- g_ptr_array_add(priv->dns_options, g_strdup(new));
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-void
-nm_ip4_config_del_dns_option(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->dns_options->len);
-
- g_ptr_array_remove_index(priv->dns_options, i);
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-guint
-nm_ip4_config_get_num_dns_options(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_options->len;
-}
-
-const char *
-nm_ip4_config_get_dns_option(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->dns_options, i);
-}
-
-/*****************************************************************************/
-
-NMSettingConnectionMdns
-nm_ip4_config_mdns_get(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->mdns;
-}
-
-void
-nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns)
-{
- NM_IP4_CONFIG_GET_PRIVATE(self)->mdns = mdns;
-}
-
-NMSettingConnectionLlmnr
-nm_ip4_config_llmnr_get(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr;
-}
-
-void
-nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr)
-{
- NM_IP4_CONFIG_GET_PRIVATE(self)->llmnr = llmnr;
-}
-
-/*****************************************************************************/
-
-NMIPConfigFlags
-nm_ip4_config_get_config_flags(const NMIP4Config *self)
-{
- return NM_IP4_CONFIG_GET_PRIVATE(self)->config_flags;
-}
-
-void
-nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (mask == 0) {
- /* for convenience, accept 0 mask to set any flags. */
- mask = flags;
- }
-
- nm_assert(!NM_FLAGS_ANY(flags, ~mask));
- priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_dns_priority(NMIP4Config *self, int priority)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priority != priv->dns_priority) {
- priv->dns_priority = priority;
- _notify(self, PROP_DNS_PRIORITY);
- }
-}
-
-int
-nm_ip4_config_get_dns_priority(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_priority;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_nis_servers(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_array_set_size(priv->nis, 0);
-}
-
-void
-nm_ip4_config_add_nis_server(NMIP4Config *self, guint32 nis)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- for (i = 0; i < priv->nis->len; i++)
- if (nis == g_array_index(priv->nis, guint32, i))
- return;
-
- g_array_append_val(priv->nis, nis);
-}
-
-void
-nm_ip4_config_del_nis_server(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nis->len);
-
- g_array_remove_index(priv->nis, i);
-}
-
-guint
-nm_ip4_config_get_num_nis_servers(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nis->len;
-}
-
-guint32
-nm_ip4_config_get_nis_server(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->nis, guint32, i);
-}
-
-void
-nm_ip4_config_set_nis_domain(NMIP4Config *self, const char *domain)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_free(priv->nis_domain);
- priv->nis_domain = g_strdup(domain);
-}
-
-const char *
-nm_ip4_config_get_nis_domain(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->nis_domain;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_reset_wins(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (priv->wins->len != 0) {
- g_array_set_size(priv->wins, 0);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
- }
-}
-
-void
-nm_ip4_config_add_wins(NMIP4Config *self, guint32 wins)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(wins != 0);
-
- for (i = 0; i < priv->wins->len; i++)
- if (wins == g_array_index(priv->wins, guint32, i))
- return;
-
- g_array_append_val(priv->wins, wins);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
-}
-
-void
-nm_ip4_config_del_wins(NMIP4Config *self, guint i)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->wins->len);
-
- g_array_remove_index(priv->wins, i);
- nm_gobject_notify_together(self, PROP_WINS_SERVER_DATA, PROP_WINS_SERVERS);
-}
-
-guint
-nm_ip4_config_get_num_wins(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->wins->len;
-}
-
-guint32
-nm_ip4_config_get_wins(const NMIP4Config *self, guint i)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return g_array_index(priv->wins, guint32, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_mtu(NMIP4Config *self, guint32 mtu, NMIPConfigSource source)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- if (!mtu)
- source = NM_IP_CONFIG_SOURCE_UNKNOWN;
-
- priv->mtu = mtu;
- priv->mtu_source = source;
-}
-
-guint32
-nm_ip4_config_get_mtu(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->mtu;
-}
-
-NMIPConfigSource
-nm_ip4_config_get_mtu_source(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->mtu_source;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- priv->metered = metered;
-}
-
-gboolean
-nm_ip4_config_get_metered(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->metered;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip4_config_get_never_default(const NMIP4Config *self)
-{
- const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- return priv->never_default;
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle)
-{
- const NMIP4ConfigPrivate * priv;
- const NMDedupMultiIdxType *idx_type;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), NULL);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- idx_type = &priv->idx_ip4_addresses;
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- idx_type = &priv->idx_ip4_routes;
- break;
- default:
- g_return_val_if_reached(NULL);
- }
-
- return nm_dedup_multi_entry_get_obj(
- nm_dedup_multi_index_lookup_obj(priv->multi_idx, idx_type, needle));
-}
-
-gboolean
-nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle)
-{
- NMIP4ConfigPrivate * priv;
- NMDedupMultiIdxType *idx_type;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- guint n;
-
- g_return_val_if_fail(NM_IS_IP4_CONFIG(self), FALSE);
-
- priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- idx_type = &priv->idx_ip4_addresses;
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- idx_type = &priv->idx_ip4_routes;
- break;
- default:
- g_return_val_if_reached(FALSE);
- }
-
- n = nm_dedup_multi_index_remove_obj(priv->multi_idx,
- idx_type,
- needle,
- (gconstpointer *) &obj_old);
- if (n != 1) {
- nm_assert(n == 0);
- return FALSE;
- }
-
- nm_assert(NMP_OBJECT_GET_TYPE(obj_old) == NMP_OBJECT_GET_TYPE(needle));
-
- switch (NMP_OBJECT_GET_TYPE(obj_old)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- _notify_addresses(self);
- break;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- if (priv->best_default_route == obj_old) {
- if (nmp_object_ref_set(&priv->best_default_route,
- _nm_ip4_config_best_default_route_find(self)))
- _notify(self, PROP_GATEWAY);
- }
- _notify_routes(self);
- break;
- default:
- nm_assert_not_reached();
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-hash_u32(GChecksum *sum, guint32 n)
-{
- g_checksum_update(sum, (const guint8 *) &n, sizeof(n));
-}
-
-void
-nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only)
-{
- guint i;
- const char * s;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP4Address *address;
- const NMPlatformIP4Route * route;
- int val;
-
- g_return_if_fail(self);
- g_return_if_fail(sum);
-
- if (!dns_only) {
- nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, self, &address) {
- hash_u32(sum, address->address);
- hash_u32(sum, address->plen);
- hash_u32(sum, address->peer_address & _nm_utils_ip4_prefix_to_netmask(address->plen));
- }
-
- nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, self, &route) {
- hash_u32(sum, route->network);
- hash_u32(sum, route->plen);
- hash_u32(sum, route->gateway);
- hash_u32(sum, route->metric);
- }
-
- for (i = 0; i < nm_ip4_config_get_num_nis_servers(self); i++)
- hash_u32(sum, nm_ip4_config_get_nis_server(self, i));
-
- s = nm_ip4_config_get_nis_domain(self);
- if (s)
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_nameservers(self); i++)
- hash_u32(sum, nm_ip4_config_get_nameserver(self, i));
-
- for (i = 0; i < nm_ip4_config_get_num_wins(self); i++)
- hash_u32(sum, nm_ip4_config_get_wins(self, i));
-
- for (i = 0; i < nm_ip4_config_get_num_domains(self); i++) {
- s = nm_ip4_config_get_domain(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_searches(self); i++) {
- s = nm_ip4_config_get_search(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip4_config_get_num_dns_options(self); i++) {
- s = nm_ip4_config_get_dns_option(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- val = nm_ip4_config_mdns_get(self);
- if (val != NM_SETTING_CONNECTION_MDNS_DEFAULT)
- g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
-
- val = nm_ip4_config_llmnr_get(self);
- if (val != NM_SETTING_CONNECTION_LLMNR_DEFAULT)
- g_checksum_update(sum, (const guint8 *) &val, sizeof(val));
-
- /* FIXME(ip-config-checksum): the DNS priority should be considered relevant
- * and added into the checksum as well, but this can't be done right now
- * because in the DNS manager we rely on the fact that an empty
- * configuration (i.e. just created) has a zero checksum. This is needed to
- * avoid rewriting resolv.conf when there is no change.
- *
- * The DNS priority initial value depends on the connection type (VPN or
- * not), so it's a bit difficult to add it to checksum maintaining the
- * assumption of checksum(empty)=0
- */
-}
-
-/**
- * nm_ip4_config_equal:
- * @a: first config to compare
- * @b: second config to compare
- *
- * Compares two #NMIP4Configs for basic equality. This means that all
- * attributes must exist in the same order in both configs (addresses, routes,
- * domains, DNS servers, etc) but some attributes (address lifetimes, and address
- * and route sources) are ignored.
- *
- * Returns: %TRUE if the configurations are basically equal to each other,
- * %FALSE if not
- */
-gboolean
-nm_ip4_config_equal(const NMIP4Config *a, const NMIP4Config *b)
-{
- nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- guint8 a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- guint8 b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
-
- if (a)
- nm_ip4_config_hash(a, a_checksum, FALSE);
- if (b)
- nm_ip4_config_hash(b, b_checksum, FALSE);
-
- nm_utils_checksum_get_digest(a_checksum, a_data);
- nm_utils_checksum_get_digest(b_checksum, b_data);
- return !memcmp(a_data, b_data, sizeof(a_data));
-}
-
-/*****************************************************************************/
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
- char addr_str[NM_UTILS_INET_ADDRSTRLEN];
- GVariantBuilder builder_data;
- guint i;
-
- switch (prop_id) {
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_ADDRESS_DATA:
- case PROP_ADDRESSES:
- nm_assert(!!priv->address_data_variant == !!priv->addresses_variant);
-
- if (!priv->address_data_variant) {
- nm_utils_ip_addresses_to_dbus(AF_INET,
- nm_ip4_config_lookup_addresses(self),
- priv->best_default_route,
- NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
- &priv->address_data_variant,
- &priv->addresses_variant);
- g_variant_ref_sink(priv->address_data_variant);
- g_variant_ref_sink(priv->addresses_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ADDRESS_DATA ? priv->address_data_variant
- : priv->addresses_variant);
- break;
- case PROP_ROUTE_DATA:
- case PROP_ROUTES:
- nm_assert(!!priv->route_data_variant == !!priv->routes_variant);
-
- if (!priv->route_data_variant) {
- nm_utils_ip_routes_to_dbus(AF_INET,
- nm_ip4_config_lookup_routes(self),
- &priv->route_data_variant,
- &priv->routes_variant);
- g_variant_ref_sink(priv->route_data_variant);
- g_variant_ref_sink(priv->routes_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ROUTE_DATA ? priv->route_data_variant
- : priv->routes_variant);
- break;
- case PROP_GATEWAY:
- if (priv->best_default_route) {
- g_value_take_string(value,
- nm_utils_inet4_ntop_dup(
- NMP_OBJECT_CAST_IP4_ROUTE(priv->best_default_route)->gateway));
- } else
- g_value_set_string(value, NULL);
- break;
- case PROP_NAMESERVER_DATA:
- g_variant_builder_init(&builder_data, G_VARIANT_TYPE("aa{sv}"));
-
- for (i = 0; i < priv->nameservers->len; i++) {
- GVariantBuilder nested_builder;
-
- _nm_utils_inet4_ntop(g_array_index(priv->nameservers, in_addr_t, i), addr_str);
-
- g_variant_builder_init(&nested_builder, G_VARIANT_TYPE("a{sv}"));
- g_variant_builder_add(&nested_builder,
- "{sv}",
- "address",
- g_variant_new_string(addr_str));
- g_variant_builder_add(&builder_data, "a{sv}", &nested_builder);
- }
-
- g_value_take_variant(value, g_variant_builder_end(&builder_data));
- break;
- case PROP_NAMESERVERS:
- g_value_take_variant(
- value,
- nm_g_variant_new_au((const guint32 *) priv->nameservers->data, priv->nameservers->len));
- break;
- case PROP_DOMAINS:
- nm_utils_g_value_set_strv(value, priv->domains);
- break;
- case PROP_SEARCHES:
- nm_utils_g_value_set_strv(value, priv->searches);
- break;
- case PROP_DNS_OPTIONS:
- nm_utils_g_value_set_strv(value, priv->dns_options);
- break;
- case PROP_DNS_PRIORITY:
- g_value_set_int(value, priv->dns_priority);
- break;
- case PROP_WINS_SERVER_DATA:
- g_variant_builder_init(&builder_data, G_VARIANT_TYPE("as"));
- for (i = 0; i < priv->wins->len; i++) {
- g_variant_builder_add(
- &builder_data,
- "s",
- _nm_utils_inet4_ntop(g_array_index(priv->wins, in_addr_t, i), addr_str));
- }
- g_value_take_variant(value, g_variant_builder_end(&builder_data));
- break;
- case PROP_WINS_SERVERS:
- g_value_take_variant(
- value,
- nm_g_variant_new_au((const guint32 *) priv->wins->data, priv->wins->len));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-/*****************************************************************************/
-
-static void
-nm_ip4_config_init(NMIP4Config *self)
-{
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_addresses,
- NMP_OBJECT_TYPE_IP4_ADDRESS);
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip4_routes,
- NMP_OBJECT_TYPE_IP4_ROUTE);
-
- priv->mdns = NM_SETTING_CONNECTION_MDNS_DEFAULT;
- priv->llmnr = NM_SETTING_CONNECTION_LLMNR_DEFAULT;
- priv->nameservers = g_array_new(FALSE, FALSE, sizeof(guint32));
- priv->domains = g_ptr_array_new_with_free_func(g_free);
- priv->searches = g_ptr_array_new_with_free_func(g_free);
- priv->dns_options = g_ptr_array_new_with_free_func(g_free);
- priv->nis = g_array_new(FALSE, TRUE, sizeof(guint32));
- priv->wins = g_array_new(FALSE, TRUE, sizeof(guint32));
-}
-
-NMIP4Config *
-nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex)
-{
- g_return_val_if_fail(ifindex >= -1, NULL);
- return g_object_new(NM_TYPE_IP4_CONFIG,
- NM_IP4_CONFIG_MULTI_IDX,
- multi_idx,
- NM_IP4_CONFIG_IFINDEX,
- ifindex,
- NULL);
-}
-
-static void
-finalize(GObject *object)
-{
- NMIP4Config * self = NM_IP4_CONFIG(object);
- NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self);
-
- nm_clear_nmp_object(&priv->best_default_route);
-
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_addresses);
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip4_routes);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
-
- g_array_unref(priv->nameservers);
- g_ptr_array_unref(priv->domains);
- g_ptr_array_unref(priv->searches);
- g_ptr_array_unref(priv->dns_options);
- g_array_unref(priv->nis);
- g_free(priv->nis_domain);
- g_array_unref(priv->wins);
-
- G_OBJECT_CLASS(nm_ip4_config_parent_class)->finalize(object);
-
- nm_dedup_multi_index_unref(priv->multi_idx);
-}
-
-static const NMDBusInterfaceInfoExtended interface_info_ip4_config = {
- .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
- NM_DBUS_INTERFACE_IP4_CONFIG,
- .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
- "aau",
- NM_IP4_CONFIG_ADDRESSES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
- "aa{sv}",
- NM_IP4_CONFIG_ADDRESS_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP4_CONFIG_GATEWAY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes", "aau", NM_IP4_CONFIG_ROUTES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
- "aa{sv}",
- NM_IP4_CONFIG_ROUTE_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("NameserverData",
- "aa{sv}",
- NM_IP4_CONFIG_NAMESERVER_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
- "au",
- NM_IP4_CONFIG_NAMESERVERS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP4_CONFIG_DOMAINS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
- "as",
- NM_IP4_CONFIG_SEARCHES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
- "as",
- NM_IP4_CONFIG_DNS_OPTIONS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
- "i",
- NM_IP4_CONFIG_DNS_PRIORITY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServerData",
- "as",
- NM_IP4_CONFIG_WINS_SERVER_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("WinsServers",
- "au",
- NM_IP4_CONFIG_WINS_SERVERS), ), ),
-};
-
-static void
-nm_ip4_config_class_init(NMIP4ConfigClass *klass)
-{
- GObjectClass * object_class = G_OBJECT_CLASS(klass);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
-
- ip_config_class->is_ipv4 = TRUE;
- ip_config_class->addr_family = AF_INET;
-
- dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP4Config");
- dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip4_config);
-
- object_class->get_property = get_property;
- object_class->set_property = set_property;
- object_class->finalize = finalize;
-
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_IP4_CONFIG_MULTI_IDX,
- "",
- "",
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_IP4_CONFIG_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESS_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_ADDRESS_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESSES] =
- g_param_spec_variant(NM_IP4_CONFIG_ADDRESSES,
- "",
- "",
- G_VARIANT_TYPE("aau"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTE_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_ROUTE_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTES] = g_param_spec_variant(NM_IP4_CONFIG_ROUTES,
- "",
- "",
- G_VARIANT_TYPE("aau"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_GATEWAY] = g_param_spec_string(NM_IP4_CONFIG_GATEWAY,
- "",
- "",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVER_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_NAMESERVER_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVERS] =
- g_param_spec_variant(NM_IP4_CONFIG_NAMESERVERS,
- "",
- "",
- G_VARIANT_TYPE("au"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DOMAINS] = g_param_spec_boxed(NM_IP4_CONFIG_DOMAINS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_SEARCHES] = g_param_spec_boxed(NM_IP4_CONFIG_SEARCHES,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_OPTIONS] =
- g_param_spec_boxed(NM_IP4_CONFIG_DNS_OPTIONS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_PRIORITY] = g_param_spec_int(NM_IP4_CONFIG_DNS_PRIORITY,
- "",
- "",
- G_MININT32,
- G_MAXINT32,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_WINS_SERVER_DATA] =
- g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVER_DATA,
- "",
- "",
- G_VARIANT_TYPE("as"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_WINS_SERVERS] =
- g_param_spec_variant(NM_IP4_CONFIG_WINS_SERVERS,
- "",
- "",
- G_VARIANT_TYPE("au"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}
diff --git a/src/core/nm-ip4-config.h b/src/core/nm-ip4-config.h
deleted file mode 100644
index 326b884def..0000000000
--- a/src/core/nm-ip4-config.h
+++ /dev/null
@@ -1,670 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2008 - 2013 Red Hat, Inc.
- */
-
-#ifndef __NETWORKMANAGER_IP4_CONFIG_H__
-#define __NETWORKMANAGER_IP4_CONFIG_H__
-
-#include "nm-setting-connection.h"
-
-#include "nm-setting-ip4-config.h"
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-platform/nmp-object.h"
-#include "nm-ip-config.h"
-
-/*****************************************************************************/
-
-typedef enum _NMIPConfigFlags {
- NM_IP_CONFIG_FLAG_NONE = 0,
-
- /* if set, then the merge flag NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES gets
- * ignored during merge. */
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES = (1ull << 0),
-} NMIPConfigFlags;
-
-typedef struct {
- NMDedupMultiIdxType parent;
- NMPObjectType obj_type;
-} NMIPConfigDedupMultiIdxType;
-
-void nm_ip_config_dedup_multi_idx_type_init(NMIPConfigDedupMultiIdxType *idx_type,
- NMPObjectType obj_type);
-
-/*****************************************************************************/
-
-void nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *iter, const NMIP4Config *self);
-void nm_ip_config_iter_ip4_route_init(NMDedupMultiIter *iter, const NMIP4Config *self);
-
-#define nm_ip_config_iter_ip4_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip4_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip4_address((iter), (address));)
-
-#define nm_ip_config_iter_ip4_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip4_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip4_route((iter), (route));)
-
-/*****************************************************************************/
-
-const NMPObject *_nm_ip_config_best_default_route_find_better(const NMPObject *obj_cur,
- const NMPObject *obj_cmp);
-gboolean _nm_ip_config_best_default_route_merge(const NMPObject **best_default_route,
- const NMPObject * new_candidate);
-
-/*****************************************************************************/
-
-gboolean _nm_ip_config_add_obj(NMDedupMultiIndex * multi_idx,
- NMIPConfigDedupMultiIdxType *idx_type,
- int ifindex,
- const NMPObject * obj_new,
- const NMPlatformObject * pl_new,
- gboolean merge,
- gboolean append_force,
- const NMPObject ** out_obj_old,
- const NMPObject ** out_obj_new);
-
-const NMDedupMultiEntry *_nm_ip_config_lookup_ip_route(const NMDedupMultiIndex * multi_idx,
- const NMIPConfigDedupMultiIdxType *idx_type,
- const NMPObject * needle,
- NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-#define NM_TYPE_IP4_CONFIG (nm_ip4_config_get_type())
-#define NM_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP4_CONFIG, NMIP4Config))
-#define NM_IP4_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
-#define NM_IS_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_IP4_CONFIG))
-#define NM_IS_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_IP4_CONFIG))
-#define NM_IP4_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IP4_CONFIG, NMIP4ConfigClass))
-
-typedef struct _NMIP4ConfigClass NMIP4ConfigClass;
-
-/* internal */
-#define NM_IP4_CONFIG_MULTI_IDX "multi-idx"
-#define NM_IP4_CONFIG_IFINDEX "ifindex"
-
-/* public*/
-#define NM_IP4_CONFIG_ADDRESS_DATA "address-data"
-#define NM_IP4_CONFIG_ROUTE_DATA "route-data"
-#define NM_IP4_CONFIG_GATEWAY "gateway"
-#define NM_IP4_CONFIG_NAMESERVER_DATA "nameserver-data"
-#define NM_IP4_CONFIG_DOMAINS "domains"
-#define NM_IP4_CONFIG_SEARCHES "searches"
-#define NM_IP4_CONFIG_DNS_OPTIONS "dns-options"
-#define NM_IP4_CONFIG_DNS_PRIORITY "dns-priority"
-#define NM_IP4_CONFIG_WINS_SERVER_DATA "wins-server-data"
-
-/* deprecated */
-#define NM_IP4_CONFIG_ADDRESSES "addresses"
-#define NM_IP4_CONFIG_ROUTES "routes"
-#define NM_IP4_CONFIG_NAMESERVERS "nameservers"
-#define NM_IP4_CONFIG_WINS_SERVERS "wins-servers"
-
-GType nm_ip4_config_get_type(void);
-
-NMIP4Config *nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex);
-
-NMIP4Config *nm_ip4_config_clone(const NMIP4Config *self);
-int nm_ip4_config_get_ifindex(const NMIP4Config *self);
-
-NMDedupMultiIndex *nm_ip4_config_get_multi_idx(const NMIP4Config *self);
-
-NMIP4Config *nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int ifindex);
-
-void nm_ip4_config_add_dependent_routes(NMIP4Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf,
- GPtrArray ** out_ip4_dev_route_blacklist);
-
-gboolean nm_ip4_config_commit(const NMIP4Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync);
-
-void nm_ip4_config_merge_setting(NMIP4Config * self,
- NMSettingIPConfig * setting,
- NMSettingConnectionMdns mdns,
- NMSettingConnectionLlmnr llmnr,
- guint32 route_table,
- guint32 route_metric);
-NMSetting *nm_ip4_config_create_setting(const NMIP4Config *self);
-
-void nm_ip4_config_merge(NMIP4Config * dst,
- const NMIP4Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty);
-void nm_ip4_config_subtract(NMIP4Config * dst,
- const NMIP4Config *src,
- guint32 default_route_metric_penalty);
-void nm_ip4_config_intersect(NMIP4Config * dst,
- const NMIP4Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-NMIP4Config *nm_ip4_config_intersect_alloc(const NMIP4Config *a,
- const NMIP4Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-gboolean
-nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *relevant_changes);
-
-const NMPObject *nm_ip4_config_best_default_route_get(const NMIP4Config *self);
-const NMPObject *_nm_ip4_config_best_default_route_find(const NMIP4Config *self);
-
-in_addr_t nmtst_ip4_config_get_gateway(NMIP4Config *config);
-
-NMSettingConnectionMdns nm_ip4_config_mdns_get(const NMIP4Config *self);
-void nm_ip4_config_mdns_set(NMIP4Config *self, NMSettingConnectionMdns mdns);
-NMSettingConnectionLlmnr nm_ip4_config_llmnr_get(const NMIP4Config *self);
-void nm_ip4_config_llmnr_set(NMIP4Config *self, NMSettingConnectionLlmnr llmnr);
-
-void nm_ip4_config_set_config_flags(NMIP4Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask);
-NMIPConfigFlags nm_ip4_config_get_config_flags(const NMIP4Config *self);
-
-const NMDedupMultiHeadEntry *nm_ip4_config_lookup_addresses(const NMIP4Config *self);
-void nm_ip4_config_reset_addresses(NMIP4Config *self);
-void nm_ip4_config_add_address(NMIP4Config *self, const NMPlatformIP4Address *address);
-void _nmtst_ip4_config_del_address(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_addresses(const NMIP4Config *self);
-const NMPlatformIP4Address *nm_ip4_config_get_first_address(const NMIP4Config *self);
-const NMPlatformIP4Address *_nmtst_ip4_config_get_address(const NMIP4Config *self, guint i);
-gboolean nm_ip4_config_address_exists(const NMIP4Config *self, const NMPlatformIP4Address *address);
-
-const NMDedupMultiHeadEntry *nm_ip4_config_lookup_routes(const NMIP4Config *self);
-void nm_ip4_config_reset_routes(NMIP4Config *self);
-void nm_ip4_config_add_route(NMIP4Config * self,
- const NMPlatformIP4Route *route,
- const NMPObject ** out_obj_new);
-void _nmtst_ip4_config_del_route(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_routes(const NMIP4Config *self);
-const NMPlatformIP4Route * _nmtst_ip4_config_get_route(const NMIP4Config *self, guint i);
-
-const NMPlatformIP4Route *nm_ip4_config_get_direct_route_for_host(const NMIP4Config *self,
- in_addr_t host,
- guint32 route_table);
-void nm_ip4_config_update_routes_metric(NMIP4Config *self, gint64 metric);
-
-void nm_ip4_config_reset_nameservers(NMIP4Config *self);
-void nm_ip4_config_add_nameserver(NMIP4Config *self, guint32 nameserver);
-
-static inline void
-_nm_ip4_config_add_nameserver(NMIP4Config *self, const guint32 *nameserver)
-{
- nm_ip4_config_add_nameserver(self, *nameserver);
-}
-
-void nm_ip4_config_del_nameserver(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_nameservers(const NMIP4Config *self);
-guint32 nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i);
-const in_addr_t *_nm_ip4_config_get_nameserver(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_domains(NMIP4Config *self);
-void nm_ip4_config_add_domain(NMIP4Config *self, const char *domain);
-void nm_ip4_config_del_domain(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_domains(const NMIP4Config *self);
-const char *nm_ip4_config_get_domain(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_searches(NMIP4Config *self);
-void nm_ip4_config_add_search(NMIP4Config *self, const char *search);
-void nm_ip4_config_del_search(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_searches(const NMIP4Config *self);
-const char *nm_ip4_config_get_search(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_reset_dns_options(NMIP4Config *self);
-void nm_ip4_config_add_dns_option(NMIP4Config *self, const char *option);
-void nm_ip4_config_del_dns_option(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_dns_options(const NMIP4Config *self);
-const char *nm_ip4_config_get_dns_option(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_set_dns_priority(NMIP4Config *self, int priority);
-int nm_ip4_config_get_dns_priority(const NMIP4Config *self);
-
-void nm_ip4_config_reset_nis_servers(NMIP4Config *self);
-void nm_ip4_config_add_nis_server(NMIP4Config *self, guint32 nis);
-void nm_ip4_config_del_nis_server(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_nis_servers(const NMIP4Config *self);
-guint32 nm_ip4_config_get_nis_server(const NMIP4Config *self, guint i);
-void nm_ip4_config_set_nis_domain(NMIP4Config *self, const char *domain);
-const char *nm_ip4_config_get_nis_domain(const NMIP4Config *self);
-
-void nm_ip4_config_reset_wins(NMIP4Config *self);
-void nm_ip4_config_add_wins(NMIP4Config *self, guint32 wins);
-void nm_ip4_config_del_wins(NMIP4Config *self, guint i);
-guint nm_ip4_config_get_num_wins(const NMIP4Config *self);
-guint32 nm_ip4_config_get_wins(const NMIP4Config *self, guint i);
-
-void nm_ip4_config_set_mtu(NMIP4Config *self, guint32 mtu, NMIPConfigSource source);
-guint32 nm_ip4_config_get_mtu(const NMIP4Config *self);
-NMIPConfigSource nm_ip4_config_get_mtu_source(const NMIP4Config *self);
-
-void nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered);
-gboolean nm_ip4_config_get_metered(const NMIP4Config *self);
-
-void nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default);
-gboolean nm_ip4_config_get_never_default(const NMIP4Config *self);
-
-const NMPObject *nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle);
-gboolean nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle);
-
-void nm_ip4_config_hash(const NMIP4Config *self, GChecksum *sum, gboolean dns_only);
-gboolean nm_ip4_config_equal(const NMIP4Config *a, const NMIP4Config *b);
-
-gboolean _nm_ip_config_check_and_add_domain(GPtrArray *array, const char *domain);
-
-void
-nm_ip_config_dump(const NMIPConfig *self, const char *detail, NMLogLevel level, NMLogDomain domain);
-
-/*****************************************************************************/
-
-#include "nm-ip6-config.h"
-
-static inline gboolean
-NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family)
-{
- if (addr_family == AF_UNSPEC)
- return NM_IS_IP4_CONFIG(config) || NM_IS_IP6_CONFIG(config);
- if (addr_family == AF_INET)
- return NM_IS_IP4_CONFIG(config);
- if (addr_family == AF_INET6)
- return NM_IS_IP6_CONFIG(config);
- g_return_val_if_reached(FALSE);
-}
-
-#if _NM_CC_SUPPORT_GENERIC
-/* _NM_IS_IP_CONFIG() is a bit unusual. If _Generic() is supported,
- * it checks whether @config is either NM_IS_IP4_CONFIG() or NM_IS_IP6_CONFIG(),
- * depending on the pointer type of @config.
- *
- * For example, with _Generic() support, the following assertions would fail:
- * NMIP6Config *ptr = (NMIP6Config *) nm_ip4_config_new(...);
- * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
- * but the following would pass:
- * NMIP4Config *ptr = nm_ip4_config_new(...);
- * g_assert (_NM_IS_IP_CONFIG (ptr, ptr));
- */
-#define _NM_IS_IP_CONFIG(typeexpr, config) \
- ({ \
- const void *const _config = (config); \
- _Generic ((typeexpr), \
- const void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- void *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- void * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- NMIPConfig *const: (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- NMIPConfig * : (NM_IS_IP4_CONFIG (_config) || NM_IS_IP6_CONFIG (_config)), \
- const NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
- const NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
- NMIP4Config *const: (NM_IS_IP4_CONFIG (_config)), \
- NMIP4Config * : (NM_IS_IP4_CONFIG (_config)), \
- const NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
- const NMIP6Config * : (NM_IS_IP6_CONFIG (_config)), \
- NMIP6Config *const: (NM_IS_IP6_CONFIG (_config)), \
- NMIP6Config * : (NM_IS_IP6_CONFIG (_config))); \
- })
-#else
-#define _NM_IS_IP_CONFIG(typeexpr, config) NM_IS_IP_CONFIG(config)
-#endif
-
-#define NM_IP_CONFIG_CAST(config) \
- ({ \
- const void *const _configx = (config); \
- \
- nm_assert(!_configx || _NM_IS_IP_CONFIG((config), _configx)); \
- NM_CONSTCAST_FULL(NMIPConfig, (config), _configx, NMIP4Config, NMIP6Config); \
- })
-
-static inline gboolean
-nm_ip_config_is_ipv4(const NMIPConfig *config)
-{
- if (NM_IP_CONFIG_GET_CLASS(config)->is_ipv4) {
- nm_assert(NM_IS_IP4_CONFIG(config));
- return TRUE;
- }
- nm_assert(NM_IS_IP6_CONFIG(config));
- return FALSE;
-}
-
-static inline int
-nm_ip_config_get_addr_family(const NMIPConfig *config)
-{
- return nm_ip_config_is_ipv4(config) ? AF_INET : AF_INET6;
-}
-
-#define _NM_IP_CONFIG_DISPATCH(config, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gconstpointer _config = (config); \
- \
- if (nm_ip_config_is_ipv4(_config)) { \
- return v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \
- } else { \
- return v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-#define _NM_IP_CONFIG_DISPATCH_VOID(config, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gconstpointer _config = (config); \
- \
- if (nm_ip_config_is_ipv4(_config)) { \
- v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \
- } else { \
- v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-static inline int
-nm_ip_config_get_ifindex(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_ifindex, nm_ip6_config_get_ifindex);
-}
-
-static inline void
-nm_ip_config_hash(const NMIPConfig *self, GChecksum *sum, gboolean dns_only)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_hash, nm_ip6_config_hash, sum, dns_only);
-}
-
-static inline gconstpointer
-nm_ip_config_get_first_address(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_first_address, nm_ip6_config_get_first_address);
-}
-
-static inline void
-nm_ip_config_iter_ip_address_init(NMDedupMultiIter *iter, const NMIPConfig *self)
-{
- if (nm_ip_config_is_ipv4(self))
- nm_ip_config_iter_ip4_address_init(iter, (const NMIP4Config *) self);
- else
- nm_ip_config_iter_ip6_address_init(iter, (const NMIP6Config *) self);
-}
-
-#define nm_ip_config_iter_ip_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip_address((iter), (address));)
-
-static inline void
-nm_ip_config_iter_ip_route_init(NMDedupMultiIter *iter, const NMIPConfig *self)
-{
- if (nm_ip_config_is_ipv4(self))
- nm_ip_config_iter_ip4_route_init(iter, (const NMIP4Config *) self);
- else
- nm_ip_config_iter_ip6_route_init(iter, (const NMIP6Config *) self);
-}
-
-#define nm_ip_config_iter_ip_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip_route((iter), (route));)
-
-static inline void
-nm_ip_config_add_address(NMIPConfig *self, const NMPlatformIPAddress *address)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_add_address,
- nm_ip6_config_add_address,
- (gconstpointer) address);
-}
-
-static inline void
-nm_ip_config_reset_addresses(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_addresses, nm_ip6_config_reset_addresses);
-}
-
-static inline void
-nm_ip_config_add_route(NMIPConfig *self,
- const NMPlatformIPRoute *new,
- const NMPObject **out_obj_new)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_add_route,
- nm_ip6_config_add_route,
- (gpointer) new,
- out_obj_new);
-}
-
-static inline void
-nm_ip_config_reset_routes(NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_routes, nm_ip6_config_reset_routes);
-}
-
-static inline int
-nm_ip_config_get_dns_priority(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_dns_priority, nm_ip6_config_get_dns_priority);
-}
-
-static inline void
-nm_ip_config_set_dns_priority(NMIPConfig *self, int priority)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_dns_priority,
- nm_ip6_config_set_dns_priority,
- priority);
-}
-
-static inline void
-nm_ip_config_add_nameserver(NMIPConfig *self, const NMIPAddr *ns)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- _nm_ip4_config_add_nameserver,
- nm_ip6_config_add_nameserver,
- (gconstpointer) ns);
-}
-
-static inline void
-nm_ip_config_reset_nameservers(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_reset_nameservers,
- nm_ip6_config_reset_nameservers);
-}
-
-static inline guint
-nm_ip_config_get_num_nameservers(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_get_num_nameservers,
- nm_ip6_config_get_num_nameservers);
-}
-
-static inline gconstpointer
-nm_ip_config_get_nameserver(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, _nm_ip4_config_get_nameserver, nm_ip6_config_get_nameserver, i);
-}
-
-static inline guint
-nm_ip_config_get_num_domains(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_num_domains, nm_ip6_config_get_num_domains);
-}
-
-static inline const char *
-nm_ip_config_get_domain(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_domain, nm_ip6_config_get_domain, i);
-}
-
-static inline void
-nm_ip_config_reset_searches(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_reset_searches, nm_ip6_config_reset_searches);
-}
-
-static inline void
-nm_ip_config_add_search(const NMIPConfig *self, const char *new)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self, nm_ip4_config_add_search, nm_ip6_config_add_search, new);
-}
-
-static inline guint
-nm_ip_config_get_num_searches(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_num_searches, nm_ip6_config_get_num_searches);
-}
-
-static inline const char *
-nm_ip_config_get_search(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_search, nm_ip6_config_get_search, i);
-}
-
-static inline guint
-nm_ip_config_get_num_dns_options(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_get_num_dns_options,
- nm_ip6_config_get_num_dns_options);
-}
-
-static inline const char *
-nm_ip_config_get_dns_option(const NMIPConfig *self, guint i)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_dns_option, nm_ip6_config_get_dns_option, i);
-}
-
-static inline const NMPObject *
-nm_ip_config_best_default_route_get(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self,
- nm_ip4_config_best_default_route_get,
- nm_ip6_config_best_default_route_get);
-}
-
-static inline NMIPConfigFlags
-nm_ip_config_get_config_flags(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_config_flags, nm_ip6_config_get_config_flags);
-}
-
-static inline void
-nm_ip_config_set_config_flags(NMIPConfig *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_config_flags,
- nm_ip6_config_set_config_flags,
- flags,
- mask);
-}
-
-static inline gboolean
-nm_ip_config_get_never_default(const NMIPConfig *self)
-{
- _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_never_default, nm_ip6_config_get_never_default);
-}
-
-static inline void
-nm_ip_config_set_never_default(NMIPConfig *self, gboolean never_default)
-{
- _NM_IP_CONFIG_DISPATCH_VOID(self,
- nm_ip4_config_set_never_default,
- nm_ip6_config_set_never_default,
- never_default);
-}
-
-#define _NM_IP_CONFIG_DISPATCH_SET_OP(_return, dst, src, v4_func, v6_func, ...) \
- G_STMT_START \
- { \
- gpointer _dst = (dst); \
- gconstpointer _src = (src); \
- \
- if (nm_ip_config_is_ipv4(_dst)) { \
- _return v4_func((NMIP4Config *) _dst, (const NMIP4Config *) _src, ##__VA_ARGS__); \
- } else { \
- _return v6_func((NMIP6Config *) _dst, (const NMIP6Config *) _src, ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-static inline void
-nm_ip_config_intersect(NMIPConfig * dst,
- const NMIPConfig *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_intersect,
- nm_ip6_config_intersect,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
-}
-
-static inline void
-nm_ip_config_subtract(NMIPConfig *dst, const NMIPConfig *src, guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_subtract,
- nm_ip6_config_subtract,
- default_route_metric_penalty);
-}
-
-static inline void
-nm_ip_config_merge(NMIPConfig * dst,
- const NMIPConfig * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(,
- dst,
- src,
- nm_ip4_config_merge,
- nm_ip6_config_merge,
- merge_flags,
- default_route_metric_penalty);
-}
-
-static inline gboolean
-nm_ip_config_replace(NMIPConfig *dst, const NMIPConfig *src, gboolean *relevant_changes)
-{
- _NM_IP_CONFIG_DISPATCH_SET_OP(
- return, dst, src, nm_ip4_config_replace, nm_ip6_config_replace, relevant_changes);
-}
-
-static inline NMIPConfig *
-nm_ip_config_intersect_alloc(const NMIPConfig *a,
- const NMIPConfig *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- if (nm_ip_config_is_ipv4(a)) {
- nm_assert(NM_IS_IP4_CONFIG(a));
- nm_assert(NM_IS_IP4_CONFIG(b));
- return (NMIPConfig *) nm_ip4_config_intersect_alloc((const NMIP4Config *) a,
- (const NMIP4Config *) b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
- } else {
- nm_assert(NM_IS_IP6_CONFIG(a));
- nm_assert(NM_IS_IP6_CONFIG(b));
- return (NMIPConfig *) nm_ip6_config_intersect_alloc((const NMIP6Config *) a,
- (const NMIP6Config *) b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty);
- }
-}
-
-gconstpointer nm_ip_config_find_first_address(const NMIPConfig * self,
- NMPlatformMatchFlags match_flag);
-
-#endif /* __NETWORKMANAGER_IP4_CONFIG_H__ */
diff --git a/src/core/nm-ip6-config.c b/src/core/nm-ip6-config.c
deleted file mode 100644
index d2ecf1759b..0000000000
--- a/src/core/nm-ip6-config.c
+++ /dev/null
@@ -1,2689 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2005 - 2017 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-ip6-config.h"
-
-#include <arpa/inet.h>
-#include <resolv.h>
-#include <linux/rtnetlink.h>
-#include <linux/if.h>
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-
-#include "nm-utils.h"
-#include "libnm-platform/nmp-object.h"
-#include "libnm-platform/nm-platform.h"
-#include "libnm-platform/nm-platform-utils.h"
-#include "libnm-core-intern/nm-core-internal.h"
-#include "NetworkManagerUtils.h"
-#include "nm-ip4-config.h"
-#include "ndisc/nm-ndisc.h"
-#include "nm-dbus-object.h"
-
-/*****************************************************************************/
-
-static gboolean
-_route_valid(const NMPlatformIP6Route *r)
-{
- struct in6_addr n;
-
- return r && r->plen <= 128
- && (memcmp(&r->network,
- nm_utils_ip6_address_clear_host_address(&n, &r->network, r->plen),
- sizeof(n))
- == 0);
-}
-
-/*****************************************************************************/
-
-typedef struct {
- int ifindex;
- int dns_priority;
- NMSettingIP6ConfigPrivacy privacy;
- GArray * nameservers;
- GPtrArray * domains;
- GPtrArray * searches;
- GPtrArray * dns_options;
- GVariant * address_data_variant;
- GVariant * addresses_variant;
- GVariant * route_data_variant;
- GVariant * routes_variant;
- NMDedupMultiIndex * multi_idx;
- const NMPObject * best_default_route;
- union {
- NMIPConfigDedupMultiIdxType idx_ip6_addresses_;
- NMDedupMultiIdxType idx_ip6_addresses;
- };
- union {
- NMIPConfigDedupMultiIdxType idx_ip6_routes_;
- NMDedupMultiIdxType idx_ip6_routes;
- };
- NMIPConfigFlags config_flags;
- bool never_default : 1;
-} NMIP6ConfigPrivate;
-
-struct _NMIP6Config {
- NMIPConfig parent;
- NMIP6ConfigPrivate _priv;
-};
-
-struct _NMIP6ConfigClass {
- NMIPConfigClass parent;
-};
-
-G_DEFINE_TYPE(NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
-
-#define NM_IP6_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMIP6Config, NM_IS_IP6_CONFIG)
-
-NM_GOBJECT_PROPERTIES_DEFINE(NMIP6Config,
- PROP_MULTI_IDX,
- PROP_IFINDEX,
- PROP_ADDRESS_DATA,
- PROP_ADDRESSES,
- PROP_ROUTE_DATA,
- PROP_ROUTES,
- PROP_GATEWAY,
- PROP_NAMESERVERS,
- PROP_DOMAINS,
- PROP_SEARCHES,
- PROP_DNS_OPTIONS,
- PROP_DNS_PRIORITY, );
-
-/*****************************************************************************/
-
-static void
-_add_address(NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new);
-static void _add_route(NMIP6Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new);
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP6Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type);
-
-/*****************************************************************************/
-
-int
-nm_ip6_config_get_ifindex(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex;
-}
-
-NMDedupMultiIndex *
-nm_ip6_config_get_multi_idx(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->multi_idx;
-}
-
-void
-nm_ip6_config_set_privacy(NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- priv->privacy = privacy;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- priv->never_default = never_default;
-}
-
-gboolean
-nm_ip6_config_get_never_default(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->never_default;
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip6_config_lookup_addresses(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip6_addresses, NULL);
-}
-
-void
-nm_ip_config_iter_ip6_address_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self)
-{
- nm_assert(NM_IS_IP6_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_addresses(self));
-}
-
-/*****************************************************************************/
-
-const NMDedupMultiHeadEntry *
-nm_ip6_config_lookup_routes(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return nm_dedup_multi_index_lookup_head(priv->multi_idx, &priv->idx_ip6_routes, NULL);
-}
-
-void
-nm_ip_config_iter_ip6_route_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self)
-{
- nm_assert(NM_IS_IP6_CONFIG(self));
-
- nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_routes(self));
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip6_config_best_default_route_get(const NMIP6Config *self)
-{
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), NULL);
-
- return NM_IP6_CONFIG_GET_PRIVATE(self)->best_default_route;
-}
-
-const NMPObject *
-_nm_ip6_config_best_default_route_find(const NMIP6Config *self)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPObject *new_best_default_route = NULL;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, NULL) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route,
- ipconf_iter.current->obj);
- }
- return new_best_default_route;
-}
-
-/*****************************************************************************/
-
-static void
-_notify_addresses(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_gobject_notify_together(self, PROP_ADDRESS_DATA, PROP_ADDRESSES);
-}
-
-static void
-_notify_routes(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_assert(priv->best_default_route == _nm_ip6_config_best_default_route_find(self));
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
- nm_gobject_notify_together(self, PROP_ROUTE_DATA, PROP_ROUTES);
-}
-
-/*****************************************************************************/
-
-static int
-sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data)
-{
- return nm_platform_ip6_address_pretty_sort_cmp(
- NMP_OBJECT_CAST_IP6_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj),
- NMP_OBJECT_CAST_IP6_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj),
- (((NMSettingIP6ConfigPrivacy) GPOINTER_TO_INT(user_data))
- == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
-}
-
-gboolean
-_nmtst_ip6_config_addresses_sort(NMIP6Config *self)
-{
- NMIP6ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- head_entry = nm_ip6_config_lookup_addresses(self);
- if (head_entry && head_entry->len > 1) {
- gboolean changed;
- gs_free gconstpointer *addresses_old = NULL;
- guint naddr, j;
- NMDedupMultiIter iter;
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- addresses_old = nm_dedup_multi_objs_to_array_head(head_entry, NULL, NULL, &naddr);
- nm_assert(addresses_old);
- nm_assert(naddr > 0 && naddr == head_entry->len);
-
- nm_dedup_multi_head_entry_sort(head_entry,
- sort_captured_addresses,
- GINT_TO_POINTER(priv->privacy));
-
- changed = FALSE;
- j = 0;
- nm_dedup_multi_iter_for_each (&iter, head_entry) {
- nm_assert(j < naddr);
- if (iter.current->obj != addresses_old[j++])
- changed = TRUE;
- }
- nm_assert(j == naddr);
-
- if (changed) {
- _notify_addresses(self);
- return TRUE;
- }
- }
- return FALSE;
-}
-
-NMIP6Config *
-nm_ip6_config_clone(const NMIP6Config *self)
-{
- NMIP6Config *copy;
-
- copy = nm_ip6_config_new(nm_ip6_config_get_multi_idx(self), -1);
- nm_ip6_config_replace(copy, self, NULL);
-
- return copy;
-}
-
-NMIP6Config *
-nm_ip6_config_capture(NMDedupMultiIndex * multi_idx,
- NMPlatform * platform,
- int ifindex,
- NMSettingIP6ConfigPrivacy use_temporary)
-{
- NMIP6Config * self;
- NMIP6ConfigPrivate * priv;
- const NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIter iter;
- const NMPObject * plobj = NULL;
-
- nm_assert(ifindex > 0);
-
- /* Slaves have no IP configuration */
- if (nm_platform_link_get_master(platform, ifindex) > 0)
- return NULL;
-
- self = nm_ip6_config_new(multi_idx, ifindex);
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex);
- if (head_entry) {
- nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
- if (!_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- ifindex,
- plobj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- nm_assert_not_reached();
- }
- head_entry = nm_ip6_config_lookup_addresses(self);
- nm_assert(head_entry);
- nm_dedup_multi_head_entry_sort(head_entry,
- sort_captured_addresses,
- GINT_TO_POINTER(use_temporary));
- _notify_addresses(self);
- }
-
- head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ROUTE, ifindex);
-
- nmp_cache_iter_for_each (&iter, head_entry, &plobj)
- _add_route(self, plobj, NULL, NULL);
-
- return self;
-}
-
-void
-nm_ip6_config_update_routes_metric(NMIP6Config *self, gint64 metric)
-{
- gs_free NMPlatformIP6Route *routes = NULL;
- gboolean need_update = FALSE;
- const NMPlatformIP6Route * r;
- NMDedupMultiIter iter;
- guint num = 0, i = 0;
-
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- if (r->metric != metric)
- need_update = TRUE;
- num++;
- }
- if (!need_update)
- return;
-
- routes = g_new(NMPlatformIP6Route, num);
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- routes[i] = *r;
- routes[i].metric = metric;
- i++;
- }
-
- g_object_freeze_notify(G_OBJECT(self));
- nm_ip6_config_reset_routes(self);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_route(self, &routes[i], NULL);
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-void
-nm_ip6_config_add_dependent_routes(NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf)
-{
- const NMPlatformIP6Address *my_addr;
- const NMPlatformIP6Route * my_route;
- int ifindex;
- NMDedupMultiIter iter;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- ifindex = nm_ip6_config_get_ifindex(self);
- g_return_if_fail(ifindex > 0);
-
- /* For IPv6 addresses received via SLAAC/autoconf, we explicitly add the
- * device-routes (onlink) to NMIP6Config.
- *
- * For manually added IPv6 routes, add the device routes explicitly. */
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &my_addr) {
- NMPlatformIP6Route *route;
- gboolean has_peer;
- int routes_n, routes_i;
-
- if (my_addr->external)
- continue;
-
- if (NM_FLAGS_HAS(my_addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
- continue;
- if (my_addr->plen == 0)
- continue;
-
- has_peer = !IN6_IS_ADDR_UNSPECIFIED(&my_addr->peer_address);
-
- /* If we have an IPv6 peer, we add two /128 routes
- * (unless, both addresses are identical). */
- routes_n =
- (has_peer && !IN6_ARE_ADDR_EQUAL(&my_addr->address, &my_addr->peer_address)) ? 2 : 1;
-
- for (routes_i = 0; routes_i < routes_n; routes_i++) {
- nm_auto_nmpobj NMPObject *r = NULL;
-
- r = nmp_object_new(NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- route = NMP_OBJECT_CAST_IP6_ROUTE(r);
-
- route->ifindex = ifindex;
- route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
- route->table_coerced = nm_platform_route_table_coerce(route_table);
- route->metric = route_metric;
-
- if (has_peer) {
- if (routes_i == 0)
- route->network = my_addr->address;
- else
- route->network = my_addr->peer_address;
- route->plen = 128;
- } else {
- nm_utils_ip6_address_clear_host_address(&route->network,
- &my_addr->address,
- my_addr->plen);
- route->plen = my_addr->plen;
- }
-
- nm_platform_ip_route_normalize(AF_INET6, (NMPlatformIPRoute *) route);
-
- if (_lookup_route(self, r, NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
- /* we already track this route. Don't add it again. */
- } else
- _add_route(self, r, NULL, NULL);
- }
- }
-
-again:
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &my_route) {
- NMPlatformIP6Route rt;
-
- if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(my_route)
- || IN6_IS_ADDR_UNSPECIFIED(&my_route->gateway)
- || NM_IS_IP_CONFIG_SOURCE_RTPROT(my_route->rt_source)
- || nm_ip6_config_get_direct_route_for_host(
- self,
- &my_route->gateway,
- nm_platform_route_table_uncoerce(my_route->table_coerced, TRUE)))
- continue;
-
- rt = *my_route;
- rt.network = my_route->gateway;
- rt.plen = 128;
- rt.gateway = in6addr_any;
- _add_route(self, NULL, &rt, NULL);
- /* adding the route might have invalidated the iteration. Start again. */
- goto again;
- }
-}
-
-gboolean
-nm_ip6_config_commit(const NMIP6Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync,
- GPtrArray ** out_temporary_not_available)
-{
- gs_unref_ptrarray GPtrArray *addresses = NULL;
- gs_unref_ptrarray GPtrArray *routes = NULL;
- gs_unref_ptrarray GPtrArray *routes_prune = NULL;
- int ifindex;
- gboolean success = TRUE;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- ifindex = nm_ip6_config_get_ifindex(self);
- g_return_val_if_fail(ifindex > 0, FALSE);
-
- addresses =
- nm_dedup_multi_objs_to_ptr_array_head(nm_ip6_config_lookup_addresses(self), NULL, NULL);
-
- routes = nm_dedup_multi_objs_to_ptr_array_head(nm_ip6_config_lookup_routes(self), NULL, NULL);
-
- routes_prune =
- nm_platform_ip_route_get_prune_list(platform, AF_INET6, ifindex, route_table_sync);
-
- nm_platform_ip6_address_sync(platform, ifindex, addresses, FALSE);
-
- if (!nm_platform_ip_route_sync(platform,
- AF_INET6,
- ifindex,
- routes,
- routes_prune,
- out_temporary_not_available))
- success = FALSE;
-
- return success;
-}
-
-void
-nm_ip6_config_merge_setting(NMIP6Config * self,
- NMSettingIPConfig *setting,
- guint32 route_table,
- guint32 route_metric)
-{
- guint naddresses, nroutes, nnameservers, nsearches;
- const char * gateway_str;
- struct in6_addr gateway_bin;
- int i, priority;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_IP6_CONFIG(setting));
-
- naddresses = nm_setting_ip_config_get_num_addresses(setting);
- nroutes = nm_setting_ip_config_get_num_routes(setting);
- nnameservers = nm_setting_ip_config_get_num_dns(setting);
- nsearches = nm_setting_ip_config_get_num_dns_searches(setting);
-
- g_object_freeze_notify(G_OBJECT(self));
-
- /* Gateway */
- if (!nm_setting_ip_config_get_never_default(setting)
- && (gateway_str = nm_setting_ip_config_get_gateway(setting))
- && inet_pton(AF_INET6, gateway_str, &gateway_bin) == 1
- && !IN6_IS_ADDR_UNSPECIFIED(&gateway_bin)) {
- const NMPlatformIP6Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_USER,
- .gateway = gateway_bin,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
-
- _add_route(self, NULL, &r, NULL);
- }
-
- /* Addresses */
- for (i = 0; i < naddresses; i++) {
- NMIPAddress * s_addr = nm_setting_ip_config_get_address(setting, i);
- NMPlatformIP6Address address;
-
- memset(&address, 0, sizeof(address));
- nm_ip_address_get_address_binary(s_addr, &address.address);
- address.plen = nm_ip_address_get_prefix(s_addr);
- nm_assert(address.plen <= 128);
- address.lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
- address.preferred = NM_PLATFORM_LIFETIME_PERMANENT;
- address.addr_source = NM_IP_CONFIG_SOURCE_USER;
-
- _add_address(self, NULL, &address);
- }
-
- /* Routes */
- for (i = 0; i < nroutes; i++) {
- NMIPRoute * s_route = nm_setting_ip_config_get_route(setting, i);
- NMPlatformIP6Route route;
- gint64 m;
-
- if (nm_ip_route_get_family(s_route) != AF_INET6) {
- nm_assert_not_reached();
- continue;
- }
-
- memset(&route, 0, sizeof(route));
- nm_ip_route_get_dest_binary(s_route, &route.network);
-
- route.plen = nm_ip_route_get_prefix(s_route);
- nm_assert(route.plen <= 128);
-
- nm_ip_route_get_next_hop_binary(s_route, &route.gateway);
- m = nm_ip_route_get_metric(s_route);
- if (m < 0)
- route.metric = route_metric;
- else
- route.metric = nm_utils_ip6_route_metric_normalize(m);
- route.rt_source = NM_IP_CONFIG_SOURCE_USER;
-
- nm_utils_ip6_address_clear_host_address(&route.network, &route.network, route.plen);
-
- nm_utils_ip_route_attribute_to_platform(AF_INET6,
- s_route,
- NM_PLATFORM_IP_ROUTE_CAST(&route),
- route_table);
- _add_route(self, NULL, &route, NULL);
- }
-
- /* DNS */
- if (nm_setting_ip_config_get_ignore_auto_dns(setting)) {
- nm_ip6_config_reset_nameservers(self);
- nm_ip6_config_reset_domains(self);
- nm_ip6_config_reset_searches(self);
- }
- for (i = 0; i < nnameservers; i++) {
- struct in6_addr ip;
-
- if (inet_pton(AF_INET6, nm_setting_ip_config_get_dns(setting, i), &ip) == 1)
- nm_ip6_config_add_nameserver(self, &ip);
- }
- for (i = 0; i < nsearches; i++)
- nm_ip6_config_add_search(self, nm_setting_ip_config_get_dns_search(setting, i));
-
- i = 0;
- while ((i = nm_setting_ip_config_next_valid_dns_option(setting, i)) >= 0) {
- nm_ip6_config_add_dns_option(self, nm_setting_ip_config_get_dns_option(setting, i));
- i++;
- }
-
- priority = nm_setting_ip_config_get_dns_priority(setting);
- if (priority)
- nm_ip6_config_set_dns_priority(self, priority);
-
- nm_ip6_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting));
-
- g_object_thaw_notify(G_OBJECT(self));
-}
-
-NMSetting *
-nm_ip6_config_create_setting(const NMIP6Config *self, gboolean maybe_ipv6_disabled)
-{
- const NMIP6ConfigPrivate * priv;
- NMSettingIPConfig * s_ip6;
- guint nnameservers, nsearches, noptions;
- const char * method = NULL;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- int i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address;
- const NMPlatformIP6Route * route;
-
- s_ip6 = NM_SETTING_IP_CONFIG(nm_setting_ip6_config_new());
-
- if (!self) {
- g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
- return NM_SETTING(s_ip6);
- }
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nnameservers = nm_ip6_config_get_num_nameservers(self);
- nsearches = nm_ip6_config_get_num_searches(self);
- noptions = nm_ip6_config_get_num_dns_options(self);
-
- /* Addresses */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address) {
- NMIPAddress *s_addr;
-
- /* Ignore link-local address. */
- if (IN6_IS_ADDR_LINKLOCAL(&address->address)) {
- if (!method)
- method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
- continue;
- }
-
- /* Detect dynamic address */
- if (address->lifetime != NM_PLATFORM_LIFETIME_PERMANENT) {
- method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
- continue;
- }
-
- /* Static address found. */
- if (!method || strcmp(method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0)
- method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
-
- s_addr = nm_ip_address_new_binary(AF_INET6, &address->address, address->plen, NULL);
- nm_setting_ip_config_add_address(s_ip6, s_addr);
- nm_ip_address_unref(s_addr);
- }
-
- /* Gateway */
- if (priv->best_default_route && nm_setting_ip_config_get_num_addresses(s_ip6) > 0) {
- g_object_set(
- s_ip6,
- NM_SETTING_IP_CONFIG_GATEWAY,
- _nm_utils_inet6_ntop(&NMP_OBJECT_CAST_IP6_ROUTE(priv->best_default_route)->gateway,
- sbuf),
- NULL);
- }
-
- /* Use 'ignore' if the method wasn't previously set */
- if (!method) {
- method = maybe_ipv6_disabled ? NM_SETTING_IP6_CONFIG_METHOD_DISABLED
- : NM_SETTING_IP6_CONFIG_METHOD_IGNORE;
- }
-
- g_object_set(s_ip6, NM_SETTING_IP_CONFIG_METHOD, method, NULL);
-
- /* Routes */
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &route) {
- NMIPRoute *s_route;
-
- /* Ignore link-local route. */
- if (IN6_IS_ADDR_LINKLOCAL(&route->network))
- continue;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
- continue;
-
- /* Ignore routes provided by external sources */
- if (route->rt_source
- != nmp_utils_ip_config_source_round_trip_rtprot(NM_IP_CONFIG_SOURCE_USER))
- continue;
-
- s_route = nm_ip_route_new_binary(AF_INET6,
- &route->network,
- route->plen,
- &route->gateway,
- route->metric,
- NULL);
- nm_setting_ip_config_add_route(s_ip6, s_route);
- nm_ip_route_unref(s_route);
- }
-
- /* DNS */
- for (i = 0; i < nnameservers; i++) {
- const struct in6_addr *nameserver = nm_ip6_config_get_nameserver(self, i);
-
- nm_setting_ip_config_add_dns(s_ip6, _nm_utils_inet6_ntop(nameserver, sbuf));
- }
- for (i = 0; i < nsearches; i++) {
- const char *search = nm_ip6_config_get_search(self, i);
-
- nm_setting_ip_config_add_dns_search(s_ip6, search);
- }
- for (i = 0; i < noptions; i++) {
- const char *option = nm_ip6_config_get_dns_option(self, i);
-
- nm_setting_ip_config_add_dns_option(s_ip6, option);
- }
-
- g_object_set(s_ip6,
- NM_SETTING_IP_CONFIG_DNS_PRIORITY,
- nm_ip6_config_get_dns_priority(self),
- NULL);
-
- return NM_SETTING(s_ip6);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_merge(NMIP6Config * dst,
- const NMIP6Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty)
-{
- guint32 i;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address = NULL;
- const NMIP6ConfigPrivate * src_priv;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &address) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_EXTERNAL) && !address->external) {
- NMPlatformIP6Address a;
-
- a = *address;
- a.external = TRUE;
- _add_address(dst, NULL, &a);
- } else
- _add_address(dst, NMP_OBJECT_UP_CAST(address), NULL);
- }
-
- /* nameservers */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_nameservers(src); i++)
- nm_ip6_config_add_nameserver(dst, nm_ip6_config_get_nameserver(src, i));
- }
-
- /* routes */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_ROUTES)) {
- const NMPlatformIP6Route *r_src;
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r_src) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) {
- if (NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DEFAULT_ROUTES)
- && !NM_FLAGS_HAS(src_priv->config_flags,
- NM_IP_CONFIG_FLAGS_IGNORE_MERGE_NO_DEFAULT_ROUTES))
- continue;
- if (default_route_metric_penalty) {
- NMPlatformIP6Route r = *r_src;
-
- r.metric =
- nm_utils_ip_route_metric_penalize(r.metric, default_route_metric_penalty);
- _add_route(dst, NULL, &r, NULL);
- continue;
- }
- }
- _add_route(dst, ipconf_iter.current->obj, NULL, NULL);
- }
- }
-
- /* domains */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_domains(src); i++)
- nm_ip6_config_add_domain(dst, nm_ip6_config_get_domain(src, i));
- }
-
- /* dns searches */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_searches(src); i++)
- nm_ip6_config_add_search(dst, nm_ip6_config_get_search(src, i));
- }
-
- /* dns options */
- if (!NM_FLAGS_HAS(merge_flags, NM_IP_CONFIG_MERGE_NO_DNS)) {
- for (i = 0; i < nm_ip6_config_get_num_dns_options(src); i++)
- nm_ip6_config_add_dns_option(dst, nm_ip6_config_get_dns_option(src, i));
- }
-
- /* DNS priority */
- if (nm_ip6_config_get_dns_priority(src))
- nm_ip6_config_set_dns_priority(dst, nm_ip6_config_get_dns_priority(src));
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-/*****************************************************************************/
-
-static int
-_nameservers_get_index(const NMIP6Config *self, const struct in6_addr *ns)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->nameservers->len; i++) {
- const struct in6_addr *n = &g_array_index(priv->nameservers, struct in6_addr, i);
-
- if (IN6_ARE_ADDR_EQUAL(ns, n))
- return (int) i;
- }
- return -1;
-}
-
-static int
-_domains_get_index(const NMIP6Config *self, const char *domain)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->domains->len; i++) {
- const char *d = g_ptr_array_index(priv->domains, i);
-
- if (g_strcmp0(domain, d) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_searches_get_index(const NMIP6Config *self, const char *search)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->searches->len; i++) {
- const char *s = g_ptr_array_index(priv->searches, i);
-
- if (g_strcmp0(search, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-static int
-_dns_options_get_index(const NMIP6Config *self, const char *option)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- guint i;
-
- for (i = 0; i < priv->dns_options->len; i++) {
- const char *s = g_ptr_array_index(priv->dns_options, i);
-
- if (g_strcmp0(option, s) == 0)
- return (int) i;
- }
- return -1;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_ip6_config_subtract:
- * @dst: config from which to remove everything in @src
- * @src: config to remove from @dst
- * @default_route_metric_penalty: pretend that on source we applied
- * a route penalty on the default-route. It means, for default routes
- * we don't remove routes that match exactly, but those with a lower
- * metric (with the penalty removed).
-*
- * Removes everything in @src from @dst.
- */
-void
-nm_ip6_config_subtract(NMIP6Config * dst,
- const NMIP6Config *src,
- guint32 default_route_metric_penalty)
-{
- NMIP6ConfigPrivate * dst_priv;
- guint i;
- int idx;
- const NMPlatformIP6Address *a;
- const NMPlatformIP6Route * r;
- NMDedupMultiIter ipconf_iter;
- gboolean changed;
- gboolean changed_default_route;
-
- g_return_if_fail(src != NULL);
- g_return_if_fail(dst != NULL);
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- changed = FALSE;
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, src, &a) {
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses,
- NMP_OBJECT_UP_CAST(a),
- NULL))
- changed = TRUE;
- }
- if (changed)
- _notify_addresses(dst);
-
- /* nameservers */
- for (i = 0; i < nm_ip6_config_get_num_nameservers(src); i++) {
- idx = _nameservers_get_index(dst, nm_ip6_config_get_nameserver(src, i));
- if (idx >= 0)
- nm_ip6_config_del_nameserver(dst, idx);
- }
-
- /* routes */
- changed = FALSE;
- changed_default_route = FALSE;
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, src, &r) {
- const NMPObject * o_src = NMP_OBJECT_UP_CAST(r);
- NMPObject o_lookup_copy;
- const NMPObject * o_lookup;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP6Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When subtracting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_src);
- rr = NMP_OBJECT_CAST_IP6_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_src;
-
- if (nm_dedup_multi_index_remove_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes,
- o_lookup,
- (gconstpointer *) &obj_old)) {
- if (dst_priv->best_default_route == obj_old) {
- nm_clear_nmp_object(&dst_priv->best_default_route);
- changed_default_route = TRUE;
- }
- changed = TRUE;
- }
- }
- if (changed_default_route) {
- nmp_object_ref_set(&dst_priv->best_default_route,
- _nm_ip6_config_best_default_route_find(dst));
- _notify(dst, PROP_GATEWAY);
- }
- if (changed)
- _notify_routes(dst);
-
- /* domains */
- for (i = 0; i < nm_ip6_config_get_num_domains(src); i++) {
- idx = _domains_get_index(dst, nm_ip6_config_get_domain(src, i));
- if (idx >= 0)
- nm_ip6_config_del_domain(dst, idx);
- }
-
- /* dns searches */
- for (i = 0; i < nm_ip6_config_get_num_searches(src); i++) {
- idx = _searches_get_index(dst, nm_ip6_config_get_search(src, i));
- if (idx >= 0)
- nm_ip6_config_del_search(dst, idx);
- }
-
- /* dns options */
- for (i = 0; i < nm_ip6_config_get_num_dns_options(src); i++) {
- idx = _dns_options_get_index(dst, nm_ip6_config_get_dns_option(src, i));
- if (idx >= 0)
- nm_ip6_config_del_dns_option(dst, idx);
- }
-
- /* DNS priority */
- if (nm_ip6_config_get_dns_priority(src) == nm_ip6_config_get_dns_priority(dst))
- nm_ip6_config_set_dns_priority(dst, 0);
-
- g_object_thaw_notify(G_OBJECT(dst));
-}
-
-static gboolean
-_nm_ip6_config_intersect_helper(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty,
- gboolean update_dst)
-{
- NMIP6ConfigPrivate * dst_priv;
- const NMIP6ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *a;
- const NMPlatformIP6Route * r;
- gboolean changed, result = FALSE;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(src, FALSE);
- g_return_val_if_fail(dst, FALSE);
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- if (update_dst)
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* addresses */
- if (intersect_addresses) {
- changed = FALSE;
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, dst, &a) {
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip6_addresses,
- NMP_OBJECT_UP_CAST(a)))
- continue;
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (changed) {
- _notify_addresses(dst);
- result = TRUE;
- }
- }
-
- /* ignore nameservers */
-
- /* routes */
- if (!intersect_routes)
- goto skip_routes;
-
- changed = FALSE;
- new_best_default_route = NULL;
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, dst, &r) {
- const NMPObject *o_dst = NMP_OBJECT_UP_CAST(r);
- const NMPObject *o_lookup;
- NMPObject o_lookup_copy;
-
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r) && default_route_metric_penalty) {
- NMPlatformIP6Route *rr;
-
- /* the default route was penalized when merging it to the combined ip-config.
- * When intersecting the routes, we must re-do that process when comparing
- * the routes. */
- o_lookup = nmp_object_stackinit_obj(&o_lookup_copy, o_dst);
- rr = NMP_OBJECT_CAST_IP6_ROUTE(&o_lookup_copy);
- rr->metric =
- nm_utils_ip_route_metric_penalize(rr->metric, default_route_metric_penalty);
- } else
- o_lookup = o_dst;
-
- if (nm_dedup_multi_index_lookup_obj(src_priv->multi_idx,
- &src_priv->idx_ip6_routes,
- o_lookup)) {
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, o_dst);
- continue;
- }
-
- if (!update_dst)
- return TRUE;
-
- if (nm_dedup_multi_index_remove_entry(dst_priv->multi_idx, ipconf_iter.current) != 1)
- nm_assert_not_reached();
- changed = TRUE;
- }
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route)) {
- nm_assert(changed);
- _notify(dst, PROP_GATEWAY);
- }
- if (changed) {
- _notify_routes(dst);
- result = TRUE;
- }
-
-skip_routes:
- /* ignore domains */
- /* ignore dns searches */
- /* ignore dns options */
-
- if (update_dst)
- g_object_thaw_notify(G_OBJECT(dst));
-
- return result;
-}
-
-/**
- * nm_ip6_config_intersect:
- * @dst: a configuration to be updated
- * @src: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @src and @dst and updates @dst in place
- * with the result.
- */
-void
-nm_ip6_config_intersect(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- _nm_ip6_config_intersect_helper(dst,
- src,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
-}
-
-/**
- * nm_ip6_config_intersect_alloc:
- * @a: a configuration
- * @b: another configuration
- * @intersect_addresses: whether addresses should be intersected
- * @intersect_routes: whether routes should be intersected
- * @default_route_metric_penalty: the default route metric penalty
- *
- * Computes the intersection between @a and @b and returns the result in a newly
- * allocated configuration. As a special case, if @a and @b are identical (with
- * respect to the only properties considered - addresses and routes) the
- * functions returns NULL so that one of existing configuration can be reused
- * without allocation.
- *
- * Returns: the intersection between @a and @b, or %NULL if the result is equal
- * to @a and @b.
- */
-NMIP6Config *
-nm_ip6_config_intersect_alloc(const NMIP6Config *a,
- const NMIP6Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty)
-{
- NMIP6Config *a_copy;
-
- if (_nm_ip6_config_intersect_helper((NMIP6Config *) a,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- FALSE)) {
- a_copy = nm_ip6_config_clone(a);
- _nm_ip6_config_intersect_helper(a_copy,
- b,
- intersect_addresses,
- intersect_routes,
- default_route_metric_penalty,
- TRUE);
- return a_copy;
- } else
- return NULL;
-}
-
-/**
- * nm_ip6_config_replace:
- * @dst: config which will be replaced with everything in @src
- * @src: config to copy over to @dst
- * @relevant_changes: return whether there are changes to the
- * destination object that are relevant. This is equal to
- * nm_ip6_config_equal() showing any difference.
- *
- * Replaces everything in @dst with @src so that the two configurations
- * contain the same content -- with the exception of the dbus path.
- *
- * Returns: whether the @dst instance changed in any way (including minor changes,
- * that are not signaled by the output parameter @relevant_changes).
- */
-gboolean
-nm_ip6_config_replace(NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes)
-{
-#if NM_MORE_ASSERTS
- gboolean config_equal;
-#endif
- gboolean has_minor_changes = FALSE, has_relevant_changes = FALSE, are_equal;
- guint i, num;
- NMIP6ConfigPrivate * dst_priv;
- const NMIP6ConfigPrivate * src_priv;
- NMDedupMultiIter ipconf_iter_src, ipconf_iter_dst;
- const NMDedupMultiHeadEntry *head_entry_src;
- const NMPObject * new_best_default_route;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(src), FALSE);
- g_return_val_if_fail(NM_IS_IP6_CONFIG(dst), FALSE);
- g_return_val_if_fail(src != dst, FALSE);
-
-#if NM_MORE_ASSERTS
- config_equal = nm_ip6_config_equal(dst, src);
-#endif
-
- dst_priv = NM_IP6_CONFIG_GET_PRIVATE(dst);
- src_priv = NM_IP6_CONFIG_GET_PRIVATE(src);
-
- g_return_val_if_fail(src_priv->ifindex > 0, FALSE);
-
- g_object_freeze_notify(G_OBJECT(dst));
-
- /* ifindex */
- if (src_priv->ifindex != dst_priv->ifindex) {
- dst_priv->ifindex = src_priv->ifindex;
- has_minor_changes = TRUE;
- }
-
- /* addresses */
- head_entry_src = nm_ip6_config_lookup_addresses(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip6_address_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP6Address *r_src = NULL;
- const NMPlatformIP6Address *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip6_address(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip6_address(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip6_address_cmp(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (!IN6_ARE_ADDR_EQUAL(&r_src->address, &r_dst->address) || r_src->plen != r_dst->plen
- || !IN6_ARE_ADDR_EQUAL(nm_platform_ip6_address_get_peer(r_src),
- nm_platform_ip6_address_get_peer(r_dst))) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip6_addresses);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses_,
- dst_priv->ifindex,
- ipconf_iter_src.current->obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip6_addresses,
- FALSE);
- _notify_addresses(dst);
- }
-
- /* routes */
- head_entry_src = nm_ip6_config_lookup_routes(src);
- nm_dedup_multi_iter_init(&ipconf_iter_src, head_entry_src);
- nm_ip_config_iter_ip6_route_init(&ipconf_iter_dst, dst);
- are_equal = TRUE;
- while (TRUE) {
- gboolean has;
- const NMPlatformIP6Route *r_src = NULL;
- const NMPlatformIP6Route *r_dst = NULL;
-
- has = nm_platform_dedup_multi_iter_next_ip6_route(&ipconf_iter_src, &r_src);
- if (has != nm_platform_dedup_multi_iter_next_ip6_route(&ipconf_iter_dst, &r_dst)) {
- are_equal = FALSE;
- has_relevant_changes = TRUE;
- break;
- }
- if (!has)
- break;
-
- if (nm_platform_ip6_route_cmp_full(r_src, r_dst) != 0) {
- are_equal = FALSE;
- if (r_src->plen != r_dst->plen
- || !nm_utils_ip6_address_same_prefix(&r_src->network, &r_dst->network, r_src->plen)
- || r_src->metric != r_dst->metric
- || !IN6_ARE_ADDR_EQUAL(&r_src->gateway, &r_dst->gateway)) {
- has_relevant_changes = TRUE;
- break;
- }
- }
- }
- if (!are_equal) {
- has_minor_changes = TRUE;
- new_best_default_route = NULL;
- nm_dedup_multi_index_dirty_set_idx(dst_priv->multi_idx, &dst_priv->idx_ip6_routes);
- nm_dedup_multi_iter_for_each (&ipconf_iter_src, head_entry_src) {
- const NMPObject *o = ipconf_iter_src.current->obj;
- const NMPObject *obj_new;
-
- _nm_ip_config_add_obj(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes_,
- dst_priv->ifindex,
- o,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new);
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
- nm_dedup_multi_index_dirty_remove_idx(dst_priv->multi_idx,
- &dst_priv->idx_ip6_routes,
- FALSE);
- if (nmp_object_ref_set(&dst_priv->best_default_route, new_best_default_route))
- _notify(dst, PROP_GATEWAY);
- _notify_routes(dst);
- }
-
- /* nameservers */
- num = nm_ip6_config_get_num_nameservers(src);
- are_equal = num == nm_ip6_config_get_num_nameservers(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (!IN6_ARE_ADDR_EQUAL(nm_ip6_config_get_nameserver(src, i),
- nm_ip6_config_get_nameserver(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_nameservers(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_nameserver(dst, nm_ip6_config_get_nameserver(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* domains */
- num = nm_ip6_config_get_num_domains(src);
- are_equal = num == nm_ip6_config_get_num_domains(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_domain(src, i), nm_ip6_config_get_domain(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_domains(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_domain(dst, nm_ip6_config_get_domain(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns searches */
- num = nm_ip6_config_get_num_searches(src);
- are_equal = num == nm_ip6_config_get_num_searches(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_search(src, i), nm_ip6_config_get_search(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_searches(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_search(dst, nm_ip6_config_get_search(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* dns options */
- num = nm_ip6_config_get_num_dns_options(src);
- are_equal = num == nm_ip6_config_get_num_dns_options(dst);
- if (are_equal) {
- for (i = 0; i < num; i++) {
- if (g_strcmp0(nm_ip6_config_get_dns_option(src, i),
- nm_ip6_config_get_dns_option(dst, i))) {
- are_equal = FALSE;
- break;
- }
- }
- }
- if (!are_equal) {
- nm_ip6_config_reset_dns_options(dst);
- for (i = 0; i < num; i++)
- nm_ip6_config_add_dns_option(dst, nm_ip6_config_get_dns_option(src, i));
- has_relevant_changes = TRUE;
- }
-
- /* DNS priority */
- if (src_priv->dns_priority != dst_priv->dns_priority) {
- nm_ip6_config_set_dns_priority(dst, src_priv->dns_priority);
- has_minor_changes = TRUE;
- }
-
- if (src_priv->privacy != dst_priv->privacy) {
- nm_ip6_config_set_privacy(dst, src_priv->privacy);
- has_minor_changes = TRUE;
- }
-
-#if NM_MORE_ASSERTS
- /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes
- * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */
- nm_assert(config_equal == !has_relevant_changes);
-#endif
-
- g_object_thaw_notify(G_OBJECT(dst));
-
- if (relevant_changes)
- *relevant_changes = has_relevant_changes;
-
- return has_relevant_changes || has_minor_changes;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
- const NMNDiscAddress *addresses,
- guint addresses_n,
- guint8 plen,
- guint32 ifa_flags)
-{
- NMIP6ConfigPrivate *priv;
- guint i;
- gboolean changed = FALSE;
- gint32 base_time_sec;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(priv->ifindex > 0);
-
- /* the base-timestamp doesn't matter it's only an anchor for the
- * expiry. However, try to re-use the same base-time for a while
- * by rounding it to 10000 seconds.
- *
- * That is because we deduplicate and NMPlatformIP6Address instances
- * so using the same timestamps is preferable. */
- base_time_sec = nm_utils_get_monotonic_timestamp_sec();
- base_time_sec = (base_time_sec / 10000) * 10000;
- base_time_sec = NM_MAX(1, base_time_sec);
-
- nm_dedup_multi_index_dirty_set_idx(priv->multi_idx, &priv->idx_ip6_addresses);
-
- for (i = 0; i < addresses_n; i++) {
- const NMNDiscAddress *ndisc_addr = &addresses[i];
- NMPObject obj;
- NMPlatformIP6Address *a;
-
- nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ADDRESS, NULL);
- a = NMP_OBJECT_CAST_IP6_ADDRESS(&obj);
- a->ifindex = priv->ifindex;
- a->address = ndisc_addr->address;
- a->plen = plen;
- a->timestamp = base_time_sec,
- a->lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
- ndisc_addr->expiry_msec,
- TRUE),
- a->preferred = _nm_ndisc_lifetime_from_expiry(((gint64) base_time_sec) * 1000,
- ndisc_addr->expiry_preferred_msec,
- TRUE),
- a->addr_source = NM_IP_CONFIG_SOURCE_NDISC;
- a->n_ifa_flags = ifa_flags;
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- priv->ifindex,
- &obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- NULL))
- changed = TRUE;
- }
-
- if (nm_dedup_multi_index_dirty_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses, FALSE) > 0)
- changed = TRUE;
-
- if (changed)
- _notify_addresses(self);
-}
-
-void
-nm_ip6_config_reset_addresses(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses) > 0)
- _notify_addresses(self);
-}
-
-static void
-_add_address(NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_addresses_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- NULL,
- NULL))
- _notify_addresses(self);
-}
-
-/**
- * nm_ip6_config_add_address:
- * @self: the #NMIP6Config
- * @new: the new address to add to @self
- *
- * Adds the new address to @self. If an address with the same basic properties
- * (address, prefix) already exists in @self, it is overwritten with the
- * lifetime and preferred of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip6_config_add_address(NMIP6Config *self, const NMPlatformIP6Address *new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 128);
- g_return_if_fail(NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_address(self, NULL, new);
-}
-
-void
-_nmtst_ip6_config_del_address(NMIP6Config *self, guint i)
-{
- const NMPlatformIP6Address *a;
-
- a = _nmtst_ip6_config_get_address(self, i);
- if (!nm_ip6_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(a)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip6_config_get_num_addresses(const NMIP6Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip6_config_lookup_addresses(self);
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_get_first_address(const NMIP6Config *self)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *a = NULL;
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &a)
- return a;
- return NULL;
-}
-
-const NMPlatformIP6Address *
-_nmtst_ip6_config_get_address(const NMIP6Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *a = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &a) {
- if (i == j)
- return a;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_lookup_address(const NMIP6Config *self, const struct in6_addr *addr)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- NMPObject obj_stack;
- const NMDedupMultiEntry * entry;
-
- nmp_object_stackinit_id_ip6_address(&obj_stack, priv->ifindex, addr);
- entry = nm_dedup_multi_index_lookup_obj(priv->multi_idx, &priv->idx_ip6_addresses, &obj_stack);
- return entry ? NMP_OBJECT_CAST_IP6_ADDRESS(entry->obj) : NULL;
-}
-
-/**
- * nm_ip6_config_has_dad_pending_addresses
- * @self: configuration containing the addresses to check
- * @candidates: configuration with the list of addresses we are
- * interested in
- *
- * Check whether there are addresses with DAD pending in @self, that
- * are also contained in @candidates.
- *
- * Returns: %TRUE if at least one matching address was found, %FALSE
- * otherwise
- */
-gboolean
-nm_ip6_config_has_any_dad_pending(const NMIP6Config *self, const NMIP6Config *candidates)
-{
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *addr, *addr_c;
-
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &addr) {
- if (NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_TENTATIVE)
- && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_DADFAILED)
- && !NM_FLAGS_HAS(addr->n_ifa_flags, IFA_F_OPTIMISTIC)) {
- addr_c = nm_ip6_config_lookup_address(candidates, &addr->address);
- if (addr_c) {
- if (addr->plen == addr_c->plen)
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static const NMDedupMultiEntry *
-_lookup_route(const NMIP6Config *self, const NMPObject *needle, NMPlatformIPRouteCmpType cmp_type)
-{
- const NMIP6ConfigPrivate *priv;
-
- nm_assert(NM_IS_IP6_CONFIG(self));
- nm_assert(NMP_OBJECT_GET_TYPE(needle) == NMP_OBJECT_TYPE_IP6_ROUTE);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return _nm_ip_config_lookup_ip_route(priv->multi_idx, &priv->idx_ip6_routes_, needle, cmp_type);
-}
-
-void
-nm_ip6_config_reset_routes_ndisc(NMIP6Config * self,
- const NMNDiscGateway *gateways,
- guint gateways_n,
- const NMNDiscRoute * routes,
- guint routes_n,
- guint32 route_table,
- guint32 route_metric,
- gboolean kernel_support_rta_pref)
-{
- NMIP6ConfigPrivate *priv;
- guint i;
- gboolean changed = FALSE;
- const NMPObject * new_best_default_route;
-
- g_return_if_fail(NM_IS_IP6_CONFIG(self));
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(priv->ifindex > 0);
-
- nm_dedup_multi_index_dirty_set_idx(priv->multi_idx, &priv->idx_ip6_routes);
-
- new_best_default_route = NULL;
- for (i = 0; i < routes_n; i++) {
- const NMNDiscRoute *ndisc_route = &routes[i];
- NMPObject obj;
- const NMPObject * obj_new;
- NMPlatformIP6Route *r;
-
- nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
- r = NMP_OBJECT_CAST_IP6_ROUTE(&obj);
- r->ifindex = priv->ifindex;
- r->network = ndisc_route->network;
- r->plen = ndisc_route->plen;
- r->gateway = ndisc_route->gateway;
- r->rt_source = NM_IP_CONFIG_SOURCE_NDISC;
- r->table_coerced = nm_platform_route_table_coerce(route_table);
- r->metric = route_metric;
- r->rt_pref = ndisc_route->preference;
- nm_assert((NMIcmpv6RouterPref) r->rt_pref == ndisc_route->preference);
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- &obj,
- NULL,
- FALSE,
- TRUE,
- NULL,
- &obj_new))
- changed = TRUE;
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
- }
-
- if (gateways_n) {
- const NMPObject * obj_new;
- NMPlatformIP6Route r = {
- .rt_source = NM_IP_CONFIG_SOURCE_NDISC,
- .ifindex = priv->ifindex,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
- };
- const NMIcmpv6RouterPref first_pref = gateways[0].preference;
-
- for (i = 0; i < gateways_n; i++) {
- r.gateway = gateways[i].address;
- r.rt_pref = gateways[i].preference;
- nm_assert((NMIcmpv6RouterPref) r.rt_pref == gateways[i].preference);
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- NULL,
- (const NMPlatformObject *) &r,
- FALSE,
- TRUE,
- NULL,
- &obj_new))
- changed = TRUE;
- new_best_default_route =
- _nm_ip_config_best_default_route_find_better(new_best_default_route, obj_new);
-
- if (first_pref != gateways[i].preference && !kernel_support_rta_pref) {
- /* We are unable to configure a router preference. Hence, we skip all gateways
- * with a different preference from the first gateway. Note, that the gateways
- * are sorted in order of highest to lowest preference. */
- break;
- }
- }
- }
-
- if (nm_dedup_multi_index_dirty_remove_idx(priv->multi_idx, &priv->idx_ip6_routes, FALSE) > 0)
- changed = TRUE;
-
- if (nmp_object_ref_set(&priv->best_default_route, new_best_default_route)) {
- changed = TRUE;
- _notify(self, PROP_GATEWAY);
- }
-
- if (changed)
- _notify_routes(self);
-}
-
-void
-nm_ip6_config_reset_routes(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_routes) > 0) {
- if (nm_clear_nmp_object(&priv->best_default_route))
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- }
-}
-
-static void
-_add_route(NMIP6Config * self,
- const NMPObject *obj_new,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new)
-{
- NMIP6ConfigPrivate * priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- const NMPObject * obj_new_2;
-
- nm_assert((!new) != (!obj_new));
- nm_assert(!new || _route_valid(new));
- nm_assert(!obj_new || _route_valid(NMP_OBJECT_CAST_IP6_ROUTE(obj_new)));
-
- if (_nm_ip_config_add_obj(priv->multi_idx,
- &priv->idx_ip6_routes_,
- priv->ifindex,
- obj_new,
- (const NMPlatformObject *) new,
- TRUE,
- FALSE,
- &obj_old,
- &obj_new_2)) {
- gboolean changed_default_route = FALSE;
-
- if (priv->best_default_route == obj_old && obj_old != obj_new_2) {
- changed_default_route = TRUE;
- nm_clear_nmp_object(&priv->best_default_route);
- }
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
- if (_nm_ip_config_best_default_route_merge(&priv->best_default_route, obj_new_2))
- changed_default_route = TRUE;
-
- if (changed_default_route)
- _notify(self, PROP_GATEWAY);
- _notify_routes(self);
- } else
- NM_SET_OUT(out_obj_new, nmp_object_ref(obj_new_2));
-}
-
-/**
- * nm_ip6_config_add_route:
- * @self: the #NMIP6Config
- * @new: the new route to add to @self
- * @out_obj_new: (allow-none) (out): the added route object. Must be unrefed
- * by caller.
- *
- * Adds the new route to @self. If a route with the same basic properties
- * (network, prefix) already exists in @self, it is overwritten including the
- * gateway and metric of @new. The source is also overwritten by the source
- * from @new if that source is higher priority.
- */
-void
-nm_ip6_config_add_route(NMIP6Config *self,
- const NMPlatformIP6Route *new,
- const NMPObject **out_obj_new)
-{
- g_return_if_fail(self);
- g_return_if_fail(new);
- g_return_if_fail(new->plen <= 128);
- g_return_if_fail(NM_IP6_CONFIG_GET_PRIVATE(self)->ifindex > 0);
-
- _add_route(self, NULL, new, out_obj_new);
-}
-
-void
-_nmtst_ip6_config_del_route(NMIP6Config *self, guint i)
-{
- const NMPlatformIP6Route *r;
-
- r = _nmtst_ip6_config_get_route(self, i);
- if (!nm_ip6_config_nmpobj_remove(self, NMP_OBJECT_UP_CAST(r)))
- g_assert_not_reached();
-}
-
-guint
-nm_ip6_config_get_num_routes(const NMIP6Config *self)
-{
- const NMDedupMultiHeadEntry *head_entry;
-
- head_entry = nm_ip6_config_lookup_routes(self);
- nm_assert(!head_entry || head_entry->len == c_list_length(&head_entry->lst_entries_head));
- return head_entry ? head_entry->len : 0;
-}
-
-const NMPlatformIP6Route *
-_nmtst_ip6_config_get_route(const NMIP6Config *self, guint i)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Route *r = NULL;
- guint j;
-
- j = 0;
- nm_ip_config_iter_ip6_route_for_each (&iter, self, &r) {
- if (i == j)
- return r;
- j++;
- }
- g_return_val_if_reached(NULL);
-}
-
-const NMPlatformIP6Route *
-nm_ip6_config_get_direct_route_for_host(const NMIP6Config * self,
- const struct in6_addr *host,
- guint32 route_table)
-{
- const NMPlatformIP6Route *best_route = NULL;
- const NMPlatformIP6Route *item;
- NMDedupMultiIter ipconf_iter;
-
- g_return_val_if_fail(host && !IN6_IS_ADDR_UNSPECIFIED(host), NULL);
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &item) {
- if (!IN6_IS_ADDR_UNSPECIFIED(&item->gateway))
- continue;
-
- if (best_route && best_route->plen > item->plen)
- continue;
-
- if (nm_platform_route_table_uncoerce(item->table_coerced, TRUE) != route_table)
- continue;
-
- if (!nm_utils_ip6_address_same_prefix(host, &item->network, item->plen))
- continue;
-
- if (best_route && best_route->metric <= item->metric)
- continue;
-
- best_route = item;
- }
- return best_route;
-}
-
-const NMPlatformIP6Address *
-nm_ip6_config_get_subnet_for_host(const NMIP6Config *self, const struct in6_addr *host)
-{
- NMDedupMultiIter iter;
- const NMPlatformIP6Address *item;
- const NMPlatformIP6Address *subnet = NULL;
- struct in6_addr subnet2, host2;
-
- g_return_val_if_fail(host && !IN6_IS_ADDR_UNSPECIFIED(host), NULL);
-
- nm_ip_config_iter_ip6_address_for_each (&iter, self, &item) {
- if (subnet && subnet->plen >= item->plen)
- continue;
-
- nm_utils_ip6_address_clear_host_address(&host2, host, item->plen);
- nm_utils_ip6_address_clear_host_address(&subnet2, &item->address, item->plen);
-
- if (IN6_ARE_ADDR_EQUAL(&subnet2, &host2))
- subnet = item;
- }
-
- return subnet;
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_nameservers(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->nameservers->len != 0) {
- g_array_set_size(priv->nameservers, 0);
- _notify(self, PROP_NAMESERVERS);
- }
-}
-
-void
-nm_ip6_config_add_nameserver(NMIP6Config *self, const struct in6_addr *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
-
- for (i = 0; i < priv->nameservers->len; i++)
- if (IN6_ARE_ADDR_EQUAL(new, &g_array_index(priv->nameservers, struct in6_addr, i)))
- return;
-
- g_array_append_val(priv->nameservers, *new);
- _notify(self, PROP_NAMESERVERS);
-}
-
-void
-nm_ip6_config_del_nameserver(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->nameservers->len);
-
- g_array_remove_index(priv->nameservers, i);
- _notify(self, PROP_NAMESERVERS);
-}
-
-guint
-nm_ip6_config_get_num_nameservers(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->nameservers->len;
-}
-
-const struct in6_addr *
-nm_ip6_config_get_nameserver(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return &g_array_index(priv->nameservers, struct in6_addr, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_domains(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->domains->len != 0) {
- g_ptr_array_set_size(priv->domains, 0);
- _notify(self, PROP_DOMAINS);
- }
-}
-
-void
-nm_ip6_config_add_domain(NMIP6Config *self, const char *domain)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->domains, domain))
- _notify(self, PROP_DOMAINS);
-}
-
-void
-nm_ip6_config_del_domain(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->domains->len);
-
- g_ptr_array_remove_index(priv->domains, i);
- _notify(self, PROP_DOMAINS);
-}
-
-guint
-nm_ip6_config_get_num_domains(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->domains->len;
-}
-
-const char *
-nm_ip6_config_get_domain(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->domains, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_searches(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->searches->len != 0) {
- g_ptr_array_set_size(priv->searches, 0);
- _notify(self, PROP_SEARCHES);
- }
-}
-
-void
-nm_ip6_config_add_search(NMIP6Config *self, const char *search)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (_nm_ip_config_check_and_add_domain(priv->searches, search))
- _notify(self, PROP_SEARCHES);
-}
-
-void
-nm_ip6_config_del_search(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->searches->len);
-
- g_ptr_array_remove_index(priv->searches, i);
- _notify(self, PROP_SEARCHES);
-}
-
-guint
-nm_ip6_config_get_num_searches(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->searches->len;
-}
-
-const char *
-nm_ip6_config_get_search(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->searches, i);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_reset_dns_options(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priv->dns_options->len != 0) {
- g_ptr_array_set_size(priv->dns_options, 0);
- _notify(self, PROP_DNS_OPTIONS);
- }
-}
-
-void
-nm_ip6_config_add_dns_option(NMIP6Config *self, const char *new)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- int i;
-
- g_return_if_fail(new != NULL);
- g_return_if_fail(new[0] != '\0');
-
- for (i = 0; i < priv->dns_options->len; i++)
- if (!g_strcmp0(g_ptr_array_index(priv->dns_options, i), new))
- return;
-
- g_ptr_array_add(priv->dns_options, g_strdup(new));
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-void
-nm_ip6_config_del_dns_option(NMIP6Config *self, guint i)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- g_return_if_fail(i < priv->dns_options->len);
-
- g_ptr_array_remove_index(priv->dns_options, i);
- _notify(self, PROP_DNS_OPTIONS);
-}
-
-guint
-nm_ip6_config_get_num_dns_options(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_options->len;
-}
-
-const char *
-nm_ip6_config_get_dns_option(const NMIP6Config *self, guint i)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return g_ptr_array_index(priv->dns_options, i);
-}
-
-/*****************************************************************************/
-
-NMIPConfigFlags
-nm_ip6_config_get_config_flags(const NMIP6Config *self)
-{
- return NM_IP6_CONFIG_GET_PRIVATE(self)->config_flags;
-}
-
-void
-nm_ip6_config_set_config_flags(NMIP6Config *self, NMIPConfigFlags flags, NMIPConfigFlags mask)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (mask == 0) {
- /* for convenience, accept 0 mask to set any flags. */
- mask = flags;
- }
-
- nm_assert(!NM_FLAGS_ANY(flags, ~mask));
- priv->config_flags = (flags & mask) | (priv->config_flags & ~mask);
-}
-
-/*****************************************************************************/
-
-void
-nm_ip6_config_set_dns_priority(NMIP6Config *self, int priority)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- if (priority != priv->dns_priority) {
- priv->dns_priority = priority;
- _notify(self, PROP_DNS_PRIORITY);
- }
-}
-
-int
-nm_ip6_config_get_dns_priority(const NMIP6Config *self)
-{
- const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- return priv->dns_priority;
-}
-
-/*****************************************************************************/
-
-const NMPObject *
-nm_ip6_config_nmpobj_lookup(const NMIP6Config *self, const NMPObject *needle)
-{
- const NMIP6ConfigPrivate * priv;
- const NMDedupMultiIdxType *idx_type;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), NULL);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- idx_type = &priv->idx_ip6_addresses;
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- idx_type = &priv->idx_ip6_routes;
- break;
- default:
- g_return_val_if_reached(NULL);
- }
-
- return nm_dedup_multi_entry_get_obj(
- nm_dedup_multi_index_lookup_obj(priv->multi_idx, idx_type, needle));
-}
-
-gboolean
-nm_ip6_config_nmpobj_remove(NMIP6Config *self, const NMPObject *needle)
-{
- NMIP6ConfigPrivate * priv;
- NMDedupMultiIdxType *idx_type;
- nm_auto_nmpobj const NMPObject *obj_old = NULL;
- guint n;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(self), FALSE);
-
- priv = NM_IP6_CONFIG_GET_PRIVATE(self);
- switch (NMP_OBJECT_GET_TYPE(needle)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- idx_type = &priv->idx_ip6_addresses;
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- idx_type = &priv->idx_ip6_routes;
- break;
- default:
- g_return_val_if_reached(FALSE);
- }
-
- n = nm_dedup_multi_index_remove_obj(priv->multi_idx,
- idx_type,
- needle,
- (gconstpointer *) &obj_old);
- if (n != 1) {
- nm_assert(n == 0);
- return FALSE;
- }
-
- nm_assert(NMP_OBJECT_GET_TYPE(obj_old) == NMP_OBJECT_GET_TYPE(needle));
-
- switch (NMP_OBJECT_GET_TYPE(obj_old)) {
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- _notify_addresses(self);
- break;
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- if (priv->best_default_route == obj_old) {
- if (nmp_object_ref_set(&priv->best_default_route,
- _nm_ip6_config_best_default_route_find(self)))
- _notify(self, PROP_GATEWAY);
- }
- _notify_routes(self);
- break;
- default:
- nm_assert_not_reached();
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-hash_u32(GChecksum *sum, guint32 n)
-{
- g_checksum_update(sum, (const guint8 *) &n, sizeof(n));
-}
-
-static void
-hash_in6addr(GChecksum *sum, const struct in6_addr *a)
-{
- if (a)
- g_checksum_update(sum, (const guint8 *) a, sizeof(*a));
- else
- g_checksum_update(sum, (const guint8 *) &in6addr_any, sizeof(in6addr_any));
-}
-
-void
-nm_ip6_config_hash(const NMIP6Config *self, GChecksum *sum, gboolean dns_only)
-{
- guint32 i;
- const char * s;
- NMDedupMultiIter ipconf_iter;
- const NMPlatformIP6Address *address;
- const NMPlatformIP6Route * route;
-
- g_return_if_fail(self);
- g_return_if_fail(sum);
-
- if (dns_only == FALSE) {
- nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, self, &address) {
- hash_in6addr(sum, &address->address);
- hash_u32(sum, address->plen);
- }
-
- nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, self, &route) {
- hash_in6addr(sum, &route->network);
- hash_u32(sum, route->plen);
- hash_in6addr(sum, &route->gateway);
- hash_u32(sum, route->metric);
- }
- }
-
- for (i = 0; i < nm_ip6_config_get_num_nameservers(self); i++)
- hash_in6addr(sum, nm_ip6_config_get_nameserver(self, i));
-
- for (i = 0; i < nm_ip6_config_get_num_domains(self); i++) {
- s = nm_ip6_config_get_domain(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip6_config_get_num_searches(self); i++) {
- s = nm_ip6_config_get_search(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-
- for (i = 0; i < nm_ip6_config_get_num_dns_options(self); i++) {
- s = nm_ip6_config_get_dns_option(self, i);
- g_checksum_update(sum, (const guint8 *) s, strlen(s));
- }
-}
-
-/**
- * nm_ip6_config_equal:
- * @a: first config to compare
- * @b: second config to compare
- *
- * Compares two #NMIP6Configs for basic equality. This means that all
- * attributes must exist in the same order in both configs (addresses, routes,
- * domains, DNS servers, etc) but some attributes (address lifetimes, and address
- * and route sources) are ignored.
- *
- * Returns: %TRUE if the configurations are basically equal to each other,
- * %FALSE if not
- */
-gboolean
-nm_ip6_config_equal(const NMIP6Config *a, const NMIP6Config *b)
-{
- nm_auto_free_checksum GChecksum *a_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- nm_auto_free_checksum GChecksum *b_checksum = g_checksum_new(G_CHECKSUM_SHA1);
- guint8 a_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
- guint8 b_data[NM_UTILS_CHECKSUM_LENGTH_SHA1];
-
- if (a)
- nm_ip6_config_hash(a, a_checksum, FALSE);
- if (b)
- nm_ip6_config_hash(b, b_checksum, FALSE);
-
- nm_utils_checksum_get_digest(a_checksum, a_data);
- nm_utils_checksum_get_digest(b_checksum, b_data);
- return !memcmp(a_data, b_data, sizeof(a_data));
-}
-
-/*****************************************************************************/
-
-static void
-nameservers_to_gvalue(GArray *array, GValue *value)
-{
- GVariantBuilder builder;
- guint i = 0;
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("aay"));
-
- while (array && (i < array->len)) {
- struct in6_addr *addr;
-
- addr = &g_array_index(array, struct in6_addr, i++);
- g_variant_builder_add(&builder, "@ay", nm_g_variant_new_ay_in6addr(addr));
- }
-
- g_value_take_variant(value, g_variant_builder_end(&builder));
-}
-
-static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_ADDRESS_DATA:
- case PROP_ADDRESSES:
- nm_assert(!!priv->address_data_variant == !!priv->addresses_variant);
-
- if (!priv->address_data_variant) {
- nm_utils_ip_addresses_to_dbus(AF_INET6,
- nm_ip6_config_lookup_addresses(self),
- priv->best_default_route,
- priv->privacy,
- &priv->address_data_variant,
- &priv->addresses_variant);
- g_variant_ref_sink(priv->address_data_variant);
- g_variant_ref_sink(priv->addresses_variant);
- }
- g_value_set_variant(value,
- prop_id == PROP_ADDRESS_DATA ? priv->address_data_variant
- : priv->addresses_variant);
- break;
-
- case PROP_ROUTE_DATA:
- case PROP_ROUTES:
- nm_assert(!!priv->route_data_variant == !!priv->routes_variant);
-
- if (!priv->route_data_variant) {
- nm_utils_ip_routes_to_dbus(AF_INET6,
- nm_ip6_config_lookup_routes(self),
- &priv->route_data_variant,
- &priv->routes_variant);
- g_variant_ref_sink(priv->route_data_variant);
- g_variant_ref_sink(priv->routes_variant);
- }
-
- g_value_set_variant(value,
- prop_id == PROP_ROUTE_DATA ? priv->route_data_variant
- : priv->routes_variant);
- break;
- case PROP_GATEWAY:
- if (priv->best_default_route) {
- g_value_take_string(value,
- nm_utils_inet6_ntop_dup(
- &NMP_OBJECT_CAST_IP6_ROUTE(priv->best_default_route)->gateway));
- } else
- g_value_set_string(value, NULL);
- break;
- case PROP_NAMESERVERS:
- nameservers_to_gvalue(priv->nameservers, value);
- break;
- case PROP_DOMAINS:
- nm_utils_g_value_set_strv(value, priv->domains);
- break;
- case PROP_SEARCHES:
- nm_utils_g_value_set_strv(value, priv->searches);
- break;
- case PROP_DNS_OPTIONS:
- nm_utils_g_value_set_strv(value, priv->dns_options);
- break;
- case PROP_DNS_PRIORITY:
- g_value_set_int(value, priv->dns_priority);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-static void
-set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- switch (prop_id) {
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
- }
-}
-
-/*****************************************************************************/
-
-static void
-nm_ip6_config_init(NMIP6Config *self)
-{
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip6_addresses,
- NMP_OBJECT_TYPE_IP6_ADDRESS);
- nm_ip_config_dedup_multi_idx_type_init((NMIPConfigDedupMultiIdxType *) &priv->idx_ip6_routes,
- NMP_OBJECT_TYPE_IP6_ROUTE);
-
- priv->nameservers = g_array_new(FALSE, TRUE, sizeof(struct in6_addr));
- priv->domains = g_ptr_array_new_with_free_func(g_free);
- priv->searches = g_ptr_array_new_with_free_func(g_free);
- priv->dns_options = g_ptr_array_new_with_free_func(g_free);
-}
-
-NMIP6Config *
-nm_ip6_config_new(NMDedupMultiIndex *multi_idx, int ifindex)
-{
- g_return_val_if_fail(ifindex >= -1, NULL);
- return g_object_new(NM_TYPE_IP6_CONFIG,
- NM_IP6_CONFIG_MULTI_IDX,
- multi_idx,
- NM_IP6_CONFIG_IFINDEX,
- ifindex,
- NULL);
-}
-
-NMIP6Config *
-nm_ip6_config_new_cloned(const NMIP6Config *src)
-{
- NMIP6Config *new;
-
- g_return_val_if_fail(NM_IS_IP6_CONFIG(src), NULL);
-
- new = nm_ip6_config_new(nm_ip6_config_get_multi_idx(src), nm_ip6_config_get_ifindex(src));
- nm_ip6_config_replace(new, src, NULL);
- return new;
-}
-
-static void
-finalize(GObject *object)
-{
- NMIP6Config * self = NM_IP6_CONFIG(object);
- NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self);
-
- nm_clear_nmp_object(&priv->best_default_route);
-
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_addresses);
- nm_dedup_multi_index_remove_idx(priv->multi_idx, &priv->idx_ip6_routes);
-
- nm_clear_g_variant(&priv->address_data_variant);
- nm_clear_g_variant(&priv->addresses_variant);
- nm_clear_g_variant(&priv->route_data_variant);
- nm_clear_g_variant(&priv->routes_variant);
-
- g_array_unref(priv->nameservers);
- g_ptr_array_unref(priv->domains);
- g_ptr_array_unref(priv->searches);
- g_ptr_array_unref(priv->dns_options);
-
- G_OBJECT_CLASS(nm_ip6_config_parent_class)->finalize(object);
-
- nm_dedup_multi_index_unref(priv->multi_idx);
-}
-
-static const NMDBusInterfaceInfoExtended interface_info_ip6_config = {
- .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(
- NM_DBUS_INTERFACE_IP6_CONFIG,
- .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS(
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Addresses",
- "a(ayuay)",
- NM_IP6_CONFIG_ADDRESSES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("AddressData",
- "aa{sv}",
- NM_IP6_CONFIG_ADDRESS_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Gateway", "s", NM_IP6_CONFIG_GATEWAY),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Routes",
- "a(ayuayu)",
- NM_IP6_CONFIG_ROUTES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("RouteData",
- "aa{sv}",
- NM_IP6_CONFIG_ROUTE_DATA),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Nameservers",
- "aay",
- NM_IP6_CONFIG_NAMESERVERS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Domains", "as", NM_IP6_CONFIG_DOMAINS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("Searches",
- "as",
- NM_IP6_CONFIG_SEARCHES),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsOptions",
- "as",
- NM_IP6_CONFIG_DNS_OPTIONS),
- NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE("DnsPriority",
- "i",
- NM_IP6_CONFIG_DNS_PRIORITY), ), ),
-};
-
-static void
-nm_ip6_config_class_init(NMIP6ConfigClass *klass)
-{
- GObjectClass * object_class = G_OBJECT_CLASS(klass);
- NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass);
- NMIPConfigClass * ip_config_class = NM_IP_CONFIG_CLASS(klass);
-
- ip_config_class->is_ipv4 = FALSE;
- ip_config_class->addr_family = AF_INET6;
-
- dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED(NM_DBUS_PATH "/IP6Config");
- dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_ip6_config);
-
- object_class->get_property = get_property;
- object_class->set_property = set_property;
- object_class->finalize = finalize;
-
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_IP6_CONFIG_MULTI_IDX,
- "",
- "",
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_IP6_CONFIG_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESS_DATA] =
- g_param_spec_variant(NM_IP6_CONFIG_ADDRESS_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ADDRESSES] =
- g_param_spec_variant(NM_IP6_CONFIG_ADDRESSES,
- "",
- "",
- G_VARIANT_TYPE("a(ayuay)"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTE_DATA] =
- g_param_spec_variant(NM_IP6_CONFIG_ROUTE_DATA,
- "",
- "",
- G_VARIANT_TYPE("aa{sv}"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_ROUTES] = g_param_spec_variant(NM_IP6_CONFIG_ROUTES,
- "",
- "",
- G_VARIANT_TYPE("a(ayuayu)"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_GATEWAY] = g_param_spec_string(NM_IP6_CONFIG_GATEWAY,
- "",
- "",
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_NAMESERVERS] =
- g_param_spec_variant(NM_IP6_CONFIG_NAMESERVERS,
- "",
- "",
- G_VARIANT_TYPE("aay"),
- NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DOMAINS] = g_param_spec_boxed(NM_IP6_CONFIG_DOMAINS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_SEARCHES] = g_param_spec_boxed(NM_IP6_CONFIG_SEARCHES,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_OPTIONS] =
- g_param_spec_boxed(NM_IP6_CONFIG_DNS_OPTIONS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_DNS_PRIORITY] = g_param_spec_int(NM_IP6_CONFIG_DNS_PRIORITY,
- "",
- "",
- G_MININT32,
- G_MAXINT32,
- 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
-}
diff --git a/src/core/nm-ip6-config.h b/src/core/nm-ip6-config.h
deleted file mode 100644
index 8694ab0c0f..0000000000
--- a/src/core/nm-ip6-config.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2008 - 2013 Red Hat, Inc.
- */
-
-#ifndef __NETWORKMANAGER_IP6_CONFIG_H__
-#define __NETWORKMANAGER_IP6_CONFIG_H__
-
-#include <netinet/in.h>
-
-#include "nm-setting-ip6-config.h"
-
-#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-platform/nmp-object.h"
-#include "nm-ip-config.h"
-
-/*****************************************************************************/
-
-void nm_ip_config_iter_ip6_address_init(NMDedupMultiIter *iter, const NMIP6Config *self);
-void nm_ip_config_iter_ip6_route_init(NMDedupMultiIter *iter, const NMIP6Config *self);
-
-#define nm_ip_config_iter_ip6_address_for_each(iter, self, address) \
- for (nm_ip_config_iter_ip6_address_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip6_address((iter), (address));)
-
-#define nm_ip_config_iter_ip6_route_for_each(iter, self, route) \
- for (nm_ip_config_iter_ip6_route_init((iter), (self)); \
- nm_platform_dedup_multi_iter_next_ip6_route((iter), (route));)
-
-/*****************************************************************************/
-
-#define NM_TYPE_IP6_CONFIG (nm_ip6_config_get_type())
-#define NM_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IP6_CONFIG, NMIP6Config))
-#define NM_IP6_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
-#define NM_IS_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_IP6_CONFIG))
-#define NM_IS_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_IP6_CONFIG))
-#define NM_IP6_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IP6_CONFIG, NMIP6ConfigClass))
-
-typedef struct _NMIP6ConfigClass NMIP6ConfigClass;
-
-/* internal */
-#define NM_IP6_CONFIG_MULTI_IDX "multi-idx"
-#define NM_IP6_CONFIG_IFINDEX "ifindex"
-
-/* public */
-#define NM_IP6_CONFIG_ADDRESS_DATA "address-data"
-#define NM_IP6_CONFIG_ROUTE_DATA "route-data"
-#define NM_IP6_CONFIG_GATEWAY "gateway"
-#define NM_IP6_CONFIG_NAMESERVERS "nameservers"
-#define NM_IP6_CONFIG_DOMAINS "domains"
-#define NM_IP6_CONFIG_SEARCHES "searches"
-#define NM_IP6_CONFIG_DNS_OPTIONS "dns-options"
-#define NM_IP6_CONFIG_DNS_PRIORITY "dns-priority"
-
-/* deprecated */
-#define NM_IP6_CONFIG_ADDRESSES "addresses"
-#define NM_IP6_CONFIG_ROUTES "routes"
-
-GType nm_ip6_config_get_type(void);
-
-NMIP6Config *nm_ip6_config_new(struct _NMDedupMultiIndex *multi_idx, int ifindex);
-NMIP6Config *nm_ip6_config_new_cloned(const NMIP6Config *src);
-
-NMIP6Config *nm_ip6_config_clone(const NMIP6Config *self);
-int nm_ip6_config_get_ifindex(const NMIP6Config *self);
-
-struct _NMDedupMultiIndex *nm_ip6_config_get_multi_idx(const NMIP6Config *self);
-
-NMIP6Config *nm_ip6_config_capture(struct _NMDedupMultiIndex *multi_idx,
- NMPlatform * platform,
- int ifindex,
- NMSettingIP6ConfigPrivacy use_temporary);
-
-void nm_ip6_config_add_dependent_routes(NMIP6Config *self,
- guint32 route_table,
- guint32 route_metric,
- gboolean is_vrf);
-
-gboolean nm_ip6_config_commit(const NMIP6Config * self,
- NMPlatform * platform,
- NMIPRouteTableSyncMode route_table_sync,
- GPtrArray ** out_temporary_not_available);
-void nm_ip6_config_merge_setting(NMIP6Config * self,
- NMSettingIPConfig *setting,
- guint32 route_table,
- guint32 route_metric);
-NMSetting *nm_ip6_config_create_setting(const NMIP6Config *self, gboolean maybe_ipv6_disabled);
-
-void nm_ip6_config_merge(NMIP6Config * dst,
- const NMIP6Config * src,
- NMIPConfigMergeFlags merge_flags,
- guint32 default_route_metric_penalty);
-void nm_ip6_config_subtract(NMIP6Config * dst,
- const NMIP6Config *src,
- guint32 default_route_metric_penalty);
-void nm_ip6_config_intersect(NMIP6Config * dst,
- const NMIP6Config *src,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-NMIP6Config *nm_ip6_config_intersect_alloc(const NMIP6Config *a,
- const NMIP6Config *b,
- gboolean intersect_addresses,
- gboolean intersect_routes,
- guint32 default_route_metric_penalty);
-gboolean
-nm_ip6_config_replace(NMIP6Config *dst, const NMIP6Config *src, gboolean *relevant_changes);
-
-const NMPObject *nm_ip6_config_best_default_route_get(const NMIP6Config *self);
-const NMPObject *_nm_ip6_config_best_default_route_find(const NMIP6Config *self);
-
-enum _NMIPConfigFlags;
-
-void nm_ip6_config_set_config_flags(NMIP6Config * self,
- enum _NMIPConfigFlags flags,
- enum _NMIPConfigFlags mask);
-enum _NMIPConfigFlags nm_ip6_config_get_config_flags(const NMIP6Config *self);
-
-const NMDedupMultiHeadEntry *nm_ip6_config_lookup_addresses(const NMIP6Config *self);
-void nm_ip6_config_reset_addresses(NMIP6Config *self);
-void nm_ip6_config_add_address(NMIP6Config *self, const NMPlatformIP6Address *address);
-void _nmtst_ip6_config_del_address(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_addresses(const NMIP6Config *self);
-const NMPlatformIP6Address *nm_ip6_config_get_first_address(const NMIP6Config *self);
-const NMPlatformIP6Address *_nmtst_ip6_config_get_address(const NMIP6Config *self, guint i);
-gboolean nm_ip6_config_address_exists(const NMIP6Config *self, const NMPlatformIP6Address *address);
-const NMPlatformIP6Address *nm_ip6_config_lookup_address(const NMIP6Config * self,
- const struct in6_addr *addr);
-gboolean _nmtst_ip6_config_addresses_sort(NMIP6Config *self);
-gboolean nm_ip6_config_has_any_dad_pending(const NMIP6Config *self, const NMIP6Config *candidates);
-
-const NMDedupMultiHeadEntry *nm_ip6_config_lookup_routes(const NMIP6Config *self);
-void nm_ip6_config_reset_routes(NMIP6Config *self);
-void nm_ip6_config_add_route(NMIP6Config * self,
- const NMPlatformIP6Route *route,
- const NMPObject ** out_obj_new);
-void _nmtst_ip6_config_del_route(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_routes(const NMIP6Config *self);
-const NMPlatformIP6Route * _nmtst_ip6_config_get_route(const NMIP6Config *self, guint i);
-
-const NMPlatformIP6Route * nm_ip6_config_get_direct_route_for_host(const NMIP6Config * self,
- const struct in6_addr *host,
- guint32 route_table);
-const NMPlatformIP6Address *nm_ip6_config_get_subnet_for_host(const NMIP6Config * self,
- const struct in6_addr *host);
-
-void nm_ip6_config_reset_nameservers(NMIP6Config *self);
-void nm_ip6_config_add_nameserver(NMIP6Config *self, const struct in6_addr *nameserver);
-void nm_ip6_config_del_nameserver(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_nameservers(const NMIP6Config *self);
-const struct in6_addr *nm_ip6_config_get_nameserver(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_domains(NMIP6Config *self);
-void nm_ip6_config_add_domain(NMIP6Config *self, const char *domain);
-void nm_ip6_config_del_domain(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_domains(const NMIP6Config *self);
-const char *nm_ip6_config_get_domain(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_searches(NMIP6Config *self);
-void nm_ip6_config_add_search(NMIP6Config *self, const char *search);
-void nm_ip6_config_del_search(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_searches(const NMIP6Config *self);
-const char *nm_ip6_config_get_search(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_reset_dns_options(NMIP6Config *self);
-void nm_ip6_config_add_dns_option(NMIP6Config *self, const char *option);
-void nm_ip6_config_del_dns_option(NMIP6Config *self, guint i);
-guint nm_ip6_config_get_num_dns_options(const NMIP6Config *self);
-const char *nm_ip6_config_get_dns_option(const NMIP6Config *self, guint i);
-
-void nm_ip6_config_set_dns_priority(NMIP6Config *self, int priority);
-int nm_ip6_config_get_dns_priority(const NMIP6Config *self);
-
-void nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default);
-gboolean nm_ip6_config_get_never_default(const NMIP6Config *self);
-
-const NMPObject *nm_ip6_config_nmpobj_lookup(const NMIP6Config *self, const NMPObject *needle);
-gboolean nm_ip6_config_nmpobj_remove(NMIP6Config *self, const NMPObject *needle);
-
-void nm_ip6_config_hash(const NMIP6Config *self, GChecksum *sum, gboolean dns_only);
-gboolean nm_ip6_config_equal(const NMIP6Config *a, const NMIP6Config *b);
-
-void nm_ip6_config_set_privacy(NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy);
-
-struct _NMNDiscAddress;
-void nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self,
- const struct _NMNDiscAddress *addresses,
- guint addresses_n,
- guint8 plen,
- guint32 ifa_flags);
-struct _NMNDiscRoute;
-struct _NMNDiscGateway;
-void nm_ip6_config_reset_routes_ndisc(NMIP6Config * self,
- const struct _NMNDiscGateway *gateways,
- guint gateways_n,
- const struct _NMNDiscRoute * routes,
- guint routes_n,
- guint32 route_table,
- guint32 route_metric,
- gboolean kernel_support_rta_pref);
-
-void nm_ip6_config_update_routes_metric(NMIP6Config *self, gint64 metric);
-
-#endif /* __NETWORKMANAGER_IP6_CONFIG_H__ */
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c
index 51ea92f634..ec91f58548 100644
--- a/src/core/nm-l3-config-data.c
+++ b/src/core/nm-l3-config-data.c
@@ -2919,7 +2919,7 @@ nm_l3_config_data_new_clone(const NML3ConfigData *src, int ifindex)
if (ifindex <= 0)
ifindex = src->ifindex;
- self = nm_l3_config_data_new(src->multi_idx, ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN);
+ self = nm_l3_config_data_new(src->multi_idx, ifindex, src->source);
nm_l3_config_data_merge(self,
src,
NM_L3_CONFIG_MERGE_FLAGS_CLONE,
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index 2ea93677ea..44657bffa5 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -1134,9 +1134,9 @@ _l3_acd_nacd_event_down_timeout_cb(gpointer user_data)
static gboolean
_l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data)
{
- NML3Cfg *self = user_data;
- gboolean success = FALSE;
- int r;
+ gs_unref_object NML3Cfg *self = g_object_ref(user_data);
+ gboolean success = FALSE;
+ int r;
nm_assert(NM_IS_L3CFG(self));
nm_assert(self->priv.p->nacd);
@@ -1153,6 +1153,13 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data)
AcdData * acd_data;
NAcdEvent * event;
+ if (!self->priv.p->nacd) {
+ /* In the loop we emit signals, where *anything* might happen.
+ * Check that we still have the nacd instance. */
+ success = TRUE;
+ goto out;
+ }
+
r = n_acd_pop_event(self->priv.p->nacd, &event);
if (r) {
_LOGT("acd: pop-event failed with error %d", r);
diff --git a/src/core/nm-manager.c b/src/core/nm-manager.c
index c0997761c1..ac8aec4a99 100644
--- a/src/core/nm-manager.c
+++ b/src/core/nm-manager.c
@@ -2593,8 +2593,6 @@ get_existing_connection(NMManager *self, NMDevice *device, gboolean *out_generat
if (out_generated)
*out_generated = FALSE;
- nm_device_capture_initial_config(device);
-
if (!nm_device_can_assume_connections(device)) {
nm_device_assume_state_reset(device);
_LOG2D(LOGD_DEVICE, device, "assume: device cannot assume connection");
diff --git a/src/core/nm-pacrunner-manager.c b/src/core/nm-pacrunner-manager.c
index 67930dbae0..acf9269eb9 100644
--- a/src/core/nm-pacrunner-manager.c
+++ b/src/core/nm-pacrunner-manager.c
@@ -7,15 +7,14 @@
#include "nm-pacrunner-manager.h"
-#include "nm-utils.h"
-#include "NetworkManagerUtils.h"
-#include "libnm-platform/nm-platform.h"
-#include "nm-dbus-manager.h"
-#include "nm-proxy-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "c-list/src/c-list.h"
#include "libnm-glib-aux/nm-dbus-aux.h"
+#include "libnm-platform/nm-platform.h"
+
+#include "NetworkManagerUtils.h"
+#include "nm-dbus-manager.h"
+#include "nm-l3-config-data.h"
+#include "nm-utils.h"
#define PACRUNNER_DBUS_SERVICE "org.pacrunner"
#define PACRUNNER_DBUS_INTERFACE "org.pacrunner.Manager"
@@ -124,58 +123,50 @@ NM_AUTO_DEFINE_FCN0(NMPacrunnerConfId *, _nm_auto_unref_conf_id, conf_id_unref);
/*****************************************************************************/
static void
-get_ip_domains(GPtrArray *domains, NMIPConfig *ip_config)
+get_ip_domains(GPtrArray *domains, const NML3ConfigData *l3cd, int addr_family)
{
NMDedupMultiIter ipconf_iter;
char * cidr;
- guint i, num;
+ guint num;
+ guint i;
char sbuf[NM_UTILS_INET_ADDRSTRLEN];
- int addr_family;
const NMPlatformIPAddress *address;
- const NMPlatformIPRoute * routes;
-
- if (!ip_config)
- return;
+ const NMPlatformIPRoute * route;
+ const char *const * strv;
- addr_family = nm_ip_config_get_addr_family(ip_config);
-
- num = nm_ip_config_get_num_searches(ip_config);
+ strv = nm_l3_config_data_get_searches(l3cd, addr_family, &num);
for (i = 0; i < num; i++)
- g_ptr_array_add(domains, g_strdup(nm_ip_config_get_search(ip_config, i)));
+ g_ptr_array_add(domains, g_strdup(strv[i]));
- num = nm_ip_config_get_num_domains(ip_config);
+ strv = nm_l3_config_data_get_domains(l3cd, addr_family, &num);
for (i = 0; i < num; i++)
- g_ptr_array_add(domains, g_strdup(nm_ip_config_get_domain(ip_config, i)));
+ g_ptr_array_add(domains, g_strdup(strv[i]));
- nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) {
+ nm_l3_config_data_iter_ip_address_for_each (&ipconf_iter, l3cd, addr_family, &address) {
cidr = g_strdup_printf("%s/%u",
nm_utils_inet_ntop(addr_family, address->address_ptr, sbuf),
address->plen);
g_ptr_array_add(domains, cidr);
}
- nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &routes) {
- if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(routes))
+ nm_l3_config_data_iter_ip_route_for_each (&ipconf_iter, l3cd, addr_family, &route) {
+ if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route))
continue;
cidr = g_strdup_printf("%s/%u",
- nm_utils_inet_ntop(addr_family, routes->network_ptr, sbuf),
- routes->plen);
+ nm_utils_inet_ntop(addr_family, route->network_ptr, sbuf),
+ route->plen);
g_ptr_array_add(domains, cidr);
}
}
static GVariant *
-_make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config)
+_make_request_create_proxy_configuration(const char *iface, const NML3ConfigData *l3cd)
{
GVariantBuilder builder;
NMProxyConfigMethod method;
- const char * pac_url;
- const char * pac_script;
+ const char * s;
- nm_assert(NM_IS_PROXY_CONFIG(proxy_config));
+ nm_assert(NM_IS_L3_CONFIG_DATA(l3cd));
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
@@ -183,20 +174,18 @@ _make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
g_variant_builder_add(&builder, "{sv}", "Interface", g_variant_new_string(iface));
}
- method = nm_proxy_config_get_method(proxy_config);
+ method = nm_l3_config_data_get_proxy_method(l3cd);
switch (method) {
case NM_PROXY_CONFIG_METHOD_AUTO:
g_variant_builder_add(&builder, "{sv}", "Method", g_variant_new_string("auto"));
- pac_url = nm_proxy_config_get_pac_url(proxy_config);
- if (pac_url) {
- g_variant_builder_add(&builder, "{sv}", "URL", g_variant_new_string(pac_url));
- }
+ s = nm_l3_config_data_get_proxy_pac_url(l3cd);
+ if (s)
+ g_variant_builder_add(&builder, "{sv}", "URL", g_variant_new_string(s));
- pac_script = nm_proxy_config_get_pac_script(proxy_config);
- if (pac_script) {
- g_variant_builder_add(&builder, "{sv}", "Script", g_variant_new_string(pac_script));
- }
+ s = nm_l3_config_data_get_proxy_pac_script(l3cd);
+ if (s)
+ g_variant_builder_add(&builder, "{sv}", "Script", g_variant_new_string(s));
break;
case NM_PROXY_CONFIG_METHOD_UNKNOWN:
case NM_PROXY_CONFIG_METHOD_NONE:
@@ -207,15 +196,15 @@ _make_request_create_proxy_configuration(NMProxyConfig *proxy_config,
g_variant_builder_add(&builder,
"{sv}",
"BrowserOnly",
- g_variant_new_boolean(nm_proxy_config_get_browser_only(proxy_config)));
+ g_variant_new_boolean(!!nm_l3_config_data_get_proxy_browser_only(l3cd)));
- if (ip4_config || ip6_config) {
+ if (l3cd) {
gs_unref_ptrarray GPtrArray *domains = NULL;
domains = g_ptr_array_new_with_free_func(g_free);
- get_ip_domains(domains, NM_IP_CONFIG_CAST(ip4_config));
- get_ip_domains(domains, NM_IP_CONFIG_CAST(ip6_config));
+ get_ip_domains(domains, l3cd, AF_INET);
+ get_ip_domains(domains, l3cd, AF_INET6);
if (domains->len > 0) {
g_variant_builder_add(
@@ -356,10 +345,8 @@ _try_start_service_by_name(NMPacrunnerManager *self)
/**
* nm_pacrunner_manager_add:
* @self: the #NMPacrunnerManager
- * @proxy_config: proxy config of the connection
* @iface: the iface for the connection or %NULL
- * @ip4_config: IP4 config of the connection to extract domain info from
- * @ip6_config: IP6 config of the connection to extract domain info from
+ * @l3cd: the #NML3ConfigData of the connection to extract domain info from
*
* Returns: a #NMPacrunnerConfId id. The function cannot
* fail and always returns a non NULL pointer. The conf-id may
@@ -367,18 +354,14 @@ _try_start_service_by_name(NMPacrunnerManager *self)
* Note that the conf-id keeps the @self instance alive.
*/
NMPacrunnerConfId *
-nm_pacrunner_manager_add(NMPacrunnerManager *self,
- NMProxyConfig * proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config)
+nm_pacrunner_manager_add(NMPacrunnerManager *self, const char *iface, const NML3ConfigData *l3cd)
{
NMPacrunnerManagerPrivate *priv;
NMPacrunnerConfId * conf_id;
gs_free char * log_msg = NULL;
g_return_val_if_fail(NM_IS_PACRUNNER_MANAGER(self), NULL);
- g_return_val_if_fail(proxy_config, NULL);
+ g_return_val_if_fail(NM_IS_L3_CONFIG_DATA(l3cd), NULL);
priv = NM_PACRUNNER_MANAGER_GET_PRIVATE(self);
@@ -387,8 +370,7 @@ nm_pacrunner_manager_add(NMPacrunnerManager *self,
.log_id = ++priv->log_id_counter,
.refcount = 1,
.self = g_object_ref(self),
- .parameters = g_variant_ref_sink(
- _make_request_create_proxy_configuration(proxy_config, iface, ip4_config, ip6_config)),
+ .parameters = g_variant_ref_sink(_make_request_create_proxy_configuration(iface, l3cd)),
};
c_list_link_tail(&priv->conf_id_lst_head, &conf_id->conf_id_lst);
diff --git a/src/core/nm-pacrunner-manager.h b/src/core/nm-pacrunner-manager.h
index fd40f1204d..3f16908f4e 100644
--- a/src/core/nm-pacrunner-manager.h
+++ b/src/core/nm-pacrunner-manager.h
@@ -26,11 +26,8 @@ GType nm_pacrunner_manager_get_type(void);
NMPacrunnerManager *nm_pacrunner_manager_get(void);
-NMPacrunnerConfId *nm_pacrunner_manager_add(NMPacrunnerManager *self,
- NMProxyConfig * proxy_config,
- const char * iface,
- NMIP4Config * ip4_config,
- NMIP6Config * ip6_config);
+NMPacrunnerConfId *
+nm_pacrunner_manager_add(NMPacrunnerManager *self, const char *iface, const NML3ConfigData *l3cd);
void nm_pacrunner_manager_remove(NMPacrunnerConfId *conf_id);
diff --git a/src/core/nm-policy.c b/src/core/nm-policy.c
index d62a9ed07c..0ccaff1549 100644
--- a/src/core/nm-policy.c
+++ b/src/core/nm-policy.c
@@ -11,28 +11,31 @@
#include <unistd.h>
#include <netdb.h>
+#include "libnm-core-intern/nm-core-internal.h"
+#include "libnm-platform/nm-platform.h"
+#include "libnm-platform/nmp-object.h"
+
#include "NetworkManagerUtils.h"
-#include "nm-act-request.h"
-#include "nm-keep-alive.h"
#include "devices/nm-device.h"
-#include "nm-setting-ip4-config.h"
-#include "nm-setting-connection.h"
-#include "libnm-platform/nm-platform.h"
#include "dns/nm-dns-manager.h"
-#include "vpn/nm-vpn-manager.h"
+#include "nm-act-request.h"
#include "nm-auth-utils.h"
-#include "nm-firewalld-manager.h"
+#include "nm-config.h"
+#include "nm-dhcp-config.h"
#include "nm-dispatcher.h"
-#include "nm-utils.h"
-#include "libnm-core-intern/nm-core-internal.h"
+#include "nm-firewalld-manager.h"
+#include "nm-hostname-manager.h"
+#include "nm-keep-alive.h"
+#include "nm-l3-config-data.h"
#include "nm-manager.h"
-#include "settings/nm-settings.h"
-#include "settings/nm-settings-connection.h"
-#include "settings/nm-agent-manager.h"
-#include "nm-dhcp-config.h"
-#include "nm-config.h"
#include "nm-netns.h"
-#include "nm-hostname-manager.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-utils.h"
+#include "settings/nm-agent-manager.h"
+#include "settings/nm-settings-connection.h"
+#include "settings/nm-settings.h"
+#include "vpn/nm-vpn-manager.h"
/*****************************************************************************/
@@ -136,30 +139,6 @@ static NMDevice *get_default_device(NMPolicy *self, int addr_family);
/*****************************************************************************/
-static void
-_dns_manager_set_ip_config(NMDnsManager * dns_manager,
- NMIPConfig * ip_config,
- NMDnsIPConfigType ip_config_type,
- NMDevice * device)
-{
- if (device && nm_device_sys_iface_state_is_external(device)) {
- nm_dns_manager_set_ip_config(dns_manager, ip_config, NM_DNS_IP_CONFIG_TYPE_REMOVED);
- return;
- }
-
- if (NM_IN_SET(ip_config_type, NM_DNS_IP_CONFIG_TYPE_DEFAULT, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE)
- && device
- && nm_device_get_route_metric_default(nm_device_get_device_type(device))
- == NM_VPN_ROUTE_METRIC_DEFAULT) {
- /* some device types are inherently VPN. */
- ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
- }
-
- nm_dns_manager_set_ip_config(dns_manager, ip_config, ip_config_type);
-}
-
-/*****************************************************************************/
-
typedef struct {
NMPlatformIP6Address prefix;
NMDevice * device; /* The requesting ("uplink") device */
@@ -974,7 +953,7 @@ update_default_ac(NMPolicy *self, int addr_family, NMActiveConnection *best)
nm_active_connection_set_default(best, addr_family, TRUE);
}
-static gpointer
+static const NML3ConfigData *
get_best_ip_config(NMPolicy * self,
int addr_family,
const char ** out_ip_iface,
@@ -982,20 +961,21 @@ get_best_ip_config(NMPolicy * self,
NMDevice ** out_device,
NMVpnConnection ** out_vpn)
{
- NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
- gpointer conf, best_conf = NULL;
- const CList * tmp_list;
- NMActiveConnection *ac;
- guint64 best_metric = G_MAXUINT64;
- NMVpnConnection * best_vpn = NULL;
+ NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd_best = NULL;
+ const CList * tmp_list;
+ NMActiveConnection * ac;
+ guint64 best_metric = G_MAXUINT64;
+ NMVpnConnection * best_vpn = NULL;
nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- NMVpnConnection * candidate;
- NMVpnConnectionState vpn_state;
- const NMPObject * obj;
- guint32 metric;
+ const NML3ConfigData *l3cd;
+ NMVpnConnection * candidate;
+ NMVpnConnectionState vpn_state;
+ const NMPObject * obj;
+ guint32 metric;
if (!NM_IS_VPN_CONNECTION(ac))
continue;
@@ -1006,24 +986,18 @@ get_best_ip_config(NMPolicy * self,
if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
continue;
- if (addr_family == AF_INET)
- conf = nm_vpn_connection_get_ip4_config(candidate);
- else
- conf = nm_vpn_connection_get_ip6_config(candidate);
- if (!conf)
+ l3cd = nm_vpn_connection_get_l3cd(candidate, addr_family);
+ if (!l3cd)
continue;
- if (addr_family == AF_INET)
- obj = nm_ip4_config_best_default_route_get(conf);
- else
- obj = nm_ip6_config_best_default_route_get(conf);
+ obj = nm_l3_config_data_get_best_default_route(l3cd, addr_family);
if (!obj)
continue;
metric = NMP_OBJECT_CAST_IPX_ROUTE(obj)->rx.metric;
if (metric <= best_metric) {
best_metric = metric;
- best_conf = conf;
+ l3cd_best = l3cd;
best_vpn = candidate;
}
}
@@ -1033,25 +1007,20 @@ get_best_ip_config(NMPolicy * self,
NM_SET_OUT(out_vpn, best_vpn);
NM_SET_OUT(out_ac, NM_ACTIVE_CONNECTION(best_vpn));
NM_SET_OUT(out_ip_iface, nm_vpn_connection_get_ip_iface(best_vpn, TRUE));
- return best_conf;
+ return l3cd_best;
}
ac = get_best_active_connection(self, addr_family, TRUE);
if (ac) {
NMDevice *device = nm_active_connection_get_device(ac);
- nm_assert(device);
-
- if (addr_family == AF_INET)
- conf = nm_device_get_ip4_config(device);
- else
- conf = nm_device_get_ip6_config(device);
+ nm_assert(NM_IS_DEVICE(device));
NM_SET_OUT(out_device, device);
NM_SET_OUT(out_vpn, NULL);
NM_SET_OUT(out_ac, ac);
NM_SET_OUT(out_ip_iface, nm_device_get_ip_iface(device));
- return conf;
+ return nm_device_get_l3cd(device, TRUE);
}
NM_SET_OUT(out_device, NULL);
@@ -1069,8 +1038,6 @@ update_ip4_routing(NMPolicy *self, gboolean force_update)
NMVpnConnection * vpn = NULL;
NMActiveConnection *best_ac = NULL;
const char * ip_iface = NULL;
- const CList * tmp_list;
- NMActiveConnection *ac;
/* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
* so we can get (vpn != NULL && best == NULL).
@@ -1088,11 +1055,11 @@ update_ip4_routing(NMPolicy *self, gboolean force_update)
return;
if (best) {
- nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip4_config(NM_VPN_CONNECTION(ac))
- && !nm_active_connection_get_device(ac))
- nm_active_connection_set_device(ac, best);
- }
+ //XXX nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
+ //XXX if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip4_config(NM_VPN_CONNECTION(ac))
+ //XXX && !nm_active_connection_get_device(ac))
+ //XXX nm_active_connection_set_device(ac, best);
+ //XXX }
}
update_default_ac(self, AF_INET, best_ac);
@@ -1132,8 +1099,6 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
NMVpnConnection * vpn = NULL;
NMActiveConnection *best_ac = NULL;
const char * ip_iface = NULL;
- NMActiveConnection *ac;
- const CList * tmp_list;
/* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
* so we can get (vpn != NULL && best == NULL).
@@ -1151,11 +1116,11 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
return;
if (best) {
- nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
- if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip6_config(NM_VPN_CONNECTION(ac))
- && !nm_active_connection_get_device(ac))
- nm_active_connection_set_device(ac, best);
- }
+ //XXX nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
+ //XXX if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip6_config(NM_VPN_CONNECTION(ac))
+ //XXX && !nm_active_connection_get_device(ac))
+ //XXX nm_active_connection_set_device(ac, best);
+ //XXX }
}
update_default_ac(self, AF_INET6, best_ac);
@@ -1176,25 +1141,38 @@ update_ip6_routing(NMPolicy *self, gboolean force_update)
static void
update_ip_dns(NMPolicy *self, int addr_family, NMDevice *changed_device)
{
- NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- gpointer ip_config;
- const char * ip_iface = NULL;
- NMVpnConnection *vpn = NULL;
- NMDevice * device = NULL;
+ NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self);
+ const NML3ConfigData *l3cd;
+ const char * ip_iface = NULL;
+ NMVpnConnection * vpn = NULL;
+ NMDevice * device = NULL;
nm_assert_addr_family(addr_family);
- ip_config = get_best_ip_config(self, addr_family, &ip_iface, NULL, &device, &vpn);
- if (ip_config) {
+ l3cd = get_best_ip_config(self, addr_family, &ip_iface, NULL, &device, &vpn);
+ if (l3cd) {
+ NMDnsIPConfigType ip_config_type;
+
+ nm_assert(!device || NM_IS_DEVICE(device));
+ nm_assert(!vpn || NM_IS_VPN_CONNECTION(vpn));
+ nm_assert((!!device) != (!!vpn));
+
/* Tell the DNS manager this config is preferred by re-adding it with
* a different IP config type.
*/
- _dns_manager_set_ip_config(NM_POLICY_GET_PRIVATE(self)->dns_manager,
- ip_config,
- (vpn || (device && nm_device_is_vpn(device)))
- ? NM_DNS_IP_CONFIG_TYPE_VPN
- : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE,
- device);
+ if (device && nm_device_sys_iface_state_is_external(device))
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_REMOVED;
+ else if (vpn || (device && nm_device_is_vpn(device)))
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
+ else
+ ip_config_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
+
+ nm_dns_manager_set_ip_config(NM_POLICY_GET_PRIVATE(self)->dns_manager,
+ addr_family,
+ ((gconstpointer) device) ?: ((gconstpointer) vpn),
+ l3cd,
+ ip_config_type,
+ TRUE);
}
if (addr_family == AF_INET6) {
@@ -1909,9 +1887,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:
@@ -2013,27 +1989,6 @@ device_state_changed(NMDevice * device,
/* Reset auto retries back to default since connection was successful */
nm_settings_connection_autoconnect_retries_reset(sett_conn);
}
-
- /* Add device's new IPv4 and IPv6 configs to DNS */
-
- nm_dns_manager_begin_updates(priv->dns_manager, __func__);
-
- ip4_config = nm_device_get_ip4_config(device);
- if (ip4_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
- ip6_config = nm_device_get_ip6_config(device);
- if (ip6_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
-
- update_routing_and_dns(self, FALSE, device);
-
- nm_dns_manager_end_updates(priv->dns_manager, __func__);
break;
case NM_DEVICE_STATE_UNMANAGED:
case NM_DEVICE_STATE_UNAVAILABLE:
@@ -2135,24 +2090,16 @@ device_state_changed(NMDevice * device,
}
static void
-device_ip_config_changed(NMDevice * device,
- NMIPConfig *new_config,
- NMIPConfig *old_config,
- gpointer user_data)
+device_l3cd_changed(NMDevice * device,
+ const NML3ConfigData *l3cd_old,
+ const NML3ConfigData *l3cd_new,
+ gpointer user_data)
{
NMPolicyPrivate *priv = user_data;
NMPolicy * self = _PRIV_TO_SELF(priv);
- int addr_family;
- nm_assert(new_config || old_config);
- nm_assert(!new_config || NM_IS_IP_CONFIG(new_config));
- nm_assert(!old_config || NM_IS_IP_CONFIG(old_config));
-
- if (new_config) {
- addr_family = nm_ip_config_get_addr_family(new_config);
- nm_assert(!old_config || addr_family == nm_ip_config_get_addr_family(old_config));
- } else
- addr_family = nm_ip_config_get_addr_family(old_config);
+ nm_assert(!l3cd_new || NM_IS_L3_CONFIG_DATA(l3cd_new));
+ nm_assert(!l3cd_old || NM_IS_L3_CONFIG_DATA(l3cd_old));
nm_dns_manager_begin_updates(priv->dns_manager, __func__);
@@ -2161,30 +2108,25 @@ device_ip_config_changed(NMDevice * device,
* ignore IP config changes but when the device is in activated state.
* Prevents unnecessary changes to DNS information.
*/
- if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) {
- if (old_config != new_config) {
- if (new_config)
- _dns_manager_set_ip_config(priv->dns_manager,
- new_config,
- NM_DNS_IP_CONFIG_TYPE_DEFAULT,
- device);
- if (old_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- old_config,
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
- }
- update_ip_dns(self, addr_family, device);
- if (addr_family == AF_INET)
- update_ip4_routing(self, TRUE);
- else
- update_ip6_routing(self, TRUE);
- update_system_hostname(self, addr_family == AF_INET ? "ip4 conf" : "ip6 conf");
+ if (nm_device_get_state(device) < NM_DEVICE_STATE_DEACTIVATING) {
+ nm_dns_manager_set_ip_config(priv->dns_manager,
+ AF_UNSPEC,
+ device,
+ l3cd_new,
+ NM_DNS_IP_CONFIG_TYPE_DEFAULT,
+ TRUE);
+ update_ip_dns(self, AF_INET, device);
+ update_ip_dns(self, AF_INET6, device);
+ update_ip4_routing(self, TRUE);
+ update_ip6_routing(self, TRUE);
+ update_system_hostname(self, "ip conf");
} else {
- /* Old configs get removed immediately */
- if (old_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- old_config,
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ nm_dns_manager_set_ip_config(priv->dns_manager,
+ AF_UNSPEC,
+ device,
+ l3cd_old,
+ NM_DNS_IP_CONFIG_TYPE_REMOVED,
+ TRUE);
}
nm_dns_manager_end_updates(priv->dns_manager, __func__);
@@ -2225,14 +2167,7 @@ devices_list_register(NMPolicy *self, NMDevice *device)
/* Connect state-changed with _after, so that the handler is invoked after other handlers. */
g_signal_connect_after(device, NM_DEVICE_STATE_CHANGED, G_CALLBACK(device_state_changed), priv);
- g_signal_connect(device,
- NM_DEVICE_IP4_CONFIG_CHANGED,
- G_CALLBACK(device_ip_config_changed),
- priv);
- g_signal_connect(device,
- NM_DEVICE_IP6_CONFIG_CHANGED,
- G_CALLBACK(device_ip_config_changed),
- priv);
+ g_signal_connect(device, NM_DEVICE_L3CD_CHANGED, G_CALLBACK(device_l3cd_changed), priv);
g_signal_connect(device,
NM_DEVICE_IP6_PREFIX_DELEGATED,
G_CALLBACK(device_ip6_prefix_delegated),
@@ -2294,51 +2229,26 @@ device_removed(NMManager *manager, NMDevice *device, gpointer user_data)
/*****************************************************************************/
static void
-vpn_connection_activated(NMPolicy *self, NMVpnConnection *vpn)
-{
- NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
-
- nm_dns_manager_begin_updates(priv->dns_manager, __func__);
-
- ip4_config = nm_vpn_connection_get_ip4_config(vpn);
- if (ip4_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_VPN);
-
- ip6_config = nm_vpn_connection_get_ip6_config(vpn);
- if (ip6_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_VPN);
-
- update_routing_and_dns(self, TRUE, NULL);
-
- nm_dns_manager_end_updates(priv->dns_manager, __func__);
-}
-
-static void
-vpn_connection_deactivated(NMPolicy *self, NMVpnConnection *vpn)
+vpn_connection_update_dns(NMPolicy *self, NMVpnConnection *vpn, gboolean remove)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
- NMIP4Config * ip4_config;
- NMIP6Config * ip6_config;
+ int IS_IPv4;
nm_dns_manager_begin_updates(priv->dns_manager, __func__);
- ip4_config = nm_vpn_connection_get_ip4_config(vpn);
- if (ip4_config)
- nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip4_config),
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
+ int addr_family = IS_IPv4 ? AF_INET : AF_INET6;
+ const NML3ConfigData *l3cd;
- ip6_config = nm_vpn_connection_get_ip6_config(vpn);
- if (ip6_config)
+ l3cd = nm_vpn_connection_get_l3cd(vpn, addr_family);
nm_dns_manager_set_ip_config(priv->dns_manager,
- NM_IP_CONFIG_CAST(ip6_config),
- NM_DNS_IP_CONFIG_TYPE_REMOVED);
+ addr_family,
+ vpn,
+ l3cd,
+ remove ? NM_DNS_IP_CONFIG_TYPE_REMOVED
+ : NM_DNS_IP_CONFIG_TYPE_VPN,
+ TRUE);
+ }
update_routing_and_dns(self, TRUE, NULL);
@@ -2352,13 +2262,14 @@ vpn_connection_state_changed(NMVpnConnection * vpn,
NMActiveConnectionStateReason reason,
NMPolicy * self)
{
+ /* FIXME: we need to track changes to nm_vpn_connection_get_l3cd(). */
if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED)
- vpn_connection_activated(self, vpn);
+ vpn_connection_update_dns(self, vpn, FALSE);
else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) {
/* Only clean up IP/DNS if the connection ever got past IP_CONFIG */
if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET
&& old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED)
- vpn_connection_deactivated(self, vpn);
+ vpn_connection_update_dns(self, vpn, TRUE);
}
}
diff --git a/src/core/nm-proxy-config.c b/src/core/nm-proxy-config.c
deleted file mode 100644
index 49156dfae0..0000000000
--- a/src/core/nm-proxy-config.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>.
- */
-
-#include "src/core/nm-default-daemon.h"
-
-#include "nm-proxy-config.h"
-
-#include <stdlib.h>
-
-#include "libnm-core-intern/nm-core-internal.h"
-
-/*****************************************************************************/
-
-typedef struct {
- NMProxyConfigMethod method;
- gboolean browser_only;
- char * pac_url;
- char * pac_script;
-} NMProxyConfigPrivate;
-
-struct _NMProxyConfig {
- GObject parent;
- NMProxyConfigPrivate _priv;
-};
-
-struct _NMProxyConfigClass {
- GObjectClass parent;
-};
-
-G_DEFINE_TYPE(NMProxyConfig, nm_proxy_config, G_TYPE_OBJECT)
-
-#define NM_PROXY_CONFIG_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMProxyConfig, NM_IS_PROXY_CONFIG)
-
-/*****************************************************************************/
-
-void
-nm_proxy_config_set_method(NMProxyConfig *config, NMProxyConfigMethod method)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- priv->method = method;
-}
-
-NMProxyConfigMethod
-nm_proxy_config_get_method(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->method;
-}
-
-void
-nm_proxy_config_merge_setting(NMProxyConfig *config, NMSettingProxy *setting)
-{
- const char * tmp = NULL;
- NMProxyConfigPrivate *priv;
- NMSettingProxyMethod method;
-
- if (!setting)
- return;
-
- g_return_if_fail(NM_IS_SETTING_PROXY(setting));
-
- priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- nm_clear_g_free(&priv->pac_script);
-
- method = nm_setting_proxy_get_method(setting);
- switch (method) {
- case NM_SETTING_PROXY_METHOD_AUTO:
- priv->method = NM_PROXY_CONFIG_METHOD_AUTO;
-
- /* Free DHCP Obtained PAC Url (i.e Option 252)
- * only when libnm overrides it.
- */
- tmp = nm_setting_proxy_get_pac_url(setting);
- if (tmp) {
- g_free(priv->pac_url);
- priv->pac_url = g_strdup(tmp);
- }
-
- tmp = nm_setting_proxy_get_pac_script(setting);
- priv->pac_script = g_strdup(tmp);
-
- break;
- case NM_SETTING_PROXY_METHOD_NONE:
- priv->method = NM_PROXY_CONFIG_METHOD_NONE;
- break;
- }
-
- priv->browser_only = nm_setting_proxy_get_browser_only(setting);
-}
-
-gboolean
-nm_proxy_config_get_browser_only(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->browser_only;
-}
-
-void
-nm_proxy_config_set_pac_url(NMProxyConfig *config, const char *url)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- g_free(priv->pac_url);
- priv->pac_url = g_strdup(url);
-}
-
-const char *
-nm_proxy_config_get_pac_url(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->pac_url;
-}
-
-void
-nm_proxy_config_set_pac_script(NMProxyConfig *config, const char *script)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- g_free(priv->pac_script);
- priv->pac_script = g_strdup(script);
-}
-
-const char *
-nm_proxy_config_get_pac_script(const NMProxyConfig *config)
-{
- const NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- return priv->pac_script;
-}
-
-/*****************************************************************************/
-
-static void
-nm_proxy_config_init(NMProxyConfig *config)
-{
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(config);
-
- priv->method = NM_PROXY_CONFIG_METHOD_NONE;
-}
-
-NMProxyConfig *
-nm_proxy_config_new(void)
-{
- return g_object_new(NM_TYPE_PROXY_CONFIG, NULL);
-}
-
-static void
-finalize(GObject *object)
-{
- NMProxyConfig * self = NM_PROXY_CONFIG(object);
- NMProxyConfigPrivate *priv = NM_PROXY_CONFIG_GET_PRIVATE(self);
-
- g_free(priv->pac_url);
- g_free(priv->pac_script);
-
- G_OBJECT_CLASS(nm_proxy_config_parent_class)->finalize(object);
-}
-
-static void
-nm_proxy_config_class_init(NMProxyConfigClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(klass);
-
- object_class->finalize = finalize;
-}
diff --git a/src/core/nm-proxy-config.h b/src/core/nm-proxy-config.h
deleted file mode 100644
index 7b6241f849..0000000000
--- a/src/core/nm-proxy-config.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>.
- */
-
-#ifndef __NETWORKMANAGER_PROXY_CONFIG_H__
-#define __NETWORKMANAGER_PROXY_CONFIG_H__
-
-#include "nm-setting-proxy.h"
-#include "nm-l3-config-data.h"
-
-#define NM_TYPE_PROXY_CONFIG (nm_proxy_config_get_type())
-#define NM_PROXY_CONFIG(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfig))
-#define NM_PROXY_CONFIG_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
-#define NM_IS_PROXY_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_PROXY_CONFIG))
-#define NM_IS_PROXY_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_PROXY_CONFIG))
-#define NM_PROXY_CONFIG_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_PROXY_CONFIG, NMProxyConfigClass))
-
-typedef struct _NMProxyConfigClass NMProxyConfigClass;
-
-GType nm_proxy_config_get_type(void);
-
-NMProxyConfig *nm_proxy_config_new(void);
-
-void nm_proxy_config_set_method(NMProxyConfig *config, NMProxyConfigMethod method);
-NMProxyConfigMethod nm_proxy_config_get_method(const NMProxyConfig *config);
-
-void nm_proxy_config_merge_setting(NMProxyConfig *config, NMSettingProxy *setting);
-
-gboolean nm_proxy_config_get_browser_only(const NMProxyConfig *config);
-
-void nm_proxy_config_set_pac_url(NMProxyConfig *config, const char *url);
-const char *nm_proxy_config_get_pac_url(const NMProxyConfig *config);
-
-void nm_proxy_config_set_pac_script(NMProxyConfig *config, const char *script);
-const char *nm_proxy_config_get_pac_script(const NMProxyConfig *config);
-
-#endif /* __NETWORKMANAGER_PROXY_CONFIG_H__ */
diff --git a/src/core/nm-types.h b/src/core/nm-types.h
index 294cf40936..76287e4dbf 100644
--- a/src/core/nm-types.h
+++ b/src/core/nm-types.h
@@ -25,10 +25,7 @@ typedef struct _NML3Cfg NML3Cfg;
typedef struct _NML3ConfigData NML3ConfigData;
typedef struct _NMDevice NMDevice;
typedef struct _NMDhcpConfig NMDhcpConfig;
-typedef struct _NMProxyConfig NMProxyConfig;
typedef struct _NMIPConfig NMIPConfig;
-typedef struct _NMIP4Config NMIP4Config;
-typedef struct _NMIP6Config NMIP6Config;
typedef struct _NMManager NMManager;
typedef struct _NMNetns NMNetns;
typedef struct _NMPolicy NMPolicy;
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 e6790f2260..1566d67fc2 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,41 @@ 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,
+ NM_IP_CONFIG_SOURCE_PPP);
- if (mtu)
- nm_ip4_config_set_mtu(config, mtu, 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 +551,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 +605,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 +623,36 @@ 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,
+ NM_IP_CONFIG_SOURCE_PPP);
- 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 +1279,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 +1399,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 +1407,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 +1426,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/tests/test-ip4-config.c b/src/core/tests/test-ip4-config.c
index 3a095d4ad9..1b38bb2f31 100644
--- a/src/core/tests/test-ip4-config.c
+++ b/src/core/tests/test-ip4-config.c
@@ -7,7 +7,6 @@
#include <arpa/inet.h>
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/core/tests/test-ip6-config.c b/src/core/tests/test-ip6-config.c
index ddf4c789c8..5982726f9f 100644
--- a/src/core/tests/test-ip6-config.c
+++ b/src/core/tests/test-ip6-config.c
@@ -8,8 +8,6 @@
#include <arpa/inet.h>
#include <linux/if_addr.h>
-#include "nm-ip6-config.h"
-
#include "libnm-platform/nm-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/core/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c
index d06ca46adc..5733b15f8a 100644
--- a/src/core/vpn/nm-vpn-connection.c
+++ b/src/core/vpn/nm-vpn-connection.c
@@ -17,9 +17,6 @@
#include <linux/if.h>
#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 +31,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,26 +98,25 @@ typedef struct {
NMNetns *netns;
- GPtrArray *ip4_dev_route_blacklist;
+ NML3Cfg *l3cfg;
GDBusProxy * proxy;
GCancellable * cancellable;
GVariant * connect_hash;
guint connect_timeout;
- NMProxyConfig * proxy_config;
NMPacrunnerConfId *pacrunner_conf_id;
gboolean has_ip4;
- NMIP4Config * ip4_config;
- 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
- * previous configuration. Consider these instances to be owned by NMDevice. */
- NMIP4Config *last_device_ip4_config;
- NMIP6Config *last_device_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;
struct in6_addr *ip6_internal_gw;
struct in6_addr *ip6_external_gw;
@@ -351,6 +348,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 +361,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
@@ -514,9 +514,7 @@ _set_vpn_state(NMVpnConnection * self,
_get_applied_connection(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)) {
@@ -536,21 +534,19 @@ _set_vpn_state(NMVpnConnection * self,
applied,
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
NULL,
NULL,
NULL);
- if (priv->proxy_config) {
- nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
- priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
- priv->proxy_config,
- priv->ip_iface,
- priv->ip4_config,
- priv->ip6_config);
- }
+ //XXX if (priv->proxy_config) {
+ //XXX nm_pacrunner_manager_remove_clear(&priv->pacrunner_conf_id);
+ //XXX priv->pacrunner_conf_id = nm_pacrunner_manager_add(nm_pacrunner_manager_get(),
+ //XXX priv->proxy_config,
+ //XXX priv->ip_iface,
+ //XXX priv->ip4_config,
+ //XXX priv->ip6_config);
+ //XXX }
break;
case STATE_DEACTIVATING:
applied = _get_applied_connection(self);
@@ -560,18 +556,15 @@ _set_vpn_state(NMVpnConnection * self,
applied,
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),
applied,
parent_dev,
priv->ip_iface,
- priv->proxy_config,
- priv->ip4_config,
- priv->ip6_config,
+ NULL, //XXX
dispatcher_pre_down_done,
self,
&priv->dispatcher_id)) {
@@ -592,8 +585,6 @@ _set_vpn_state(NMVpnConnection * self,
_get_applied_connection(self),
parent_dev,
priv->ip_iface,
- NULL,
- NULL,
NULL);
} else {
nm_dispatcher_call_vpn(NM_DISPATCHER_ACTION_VPN_DOWN,
@@ -604,8 +595,6 @@ _set_vpn_state(NMVpnConnection * self,
NULL,
NULL,
NULL,
- NULL,
- NULL,
NULL);
}
}
@@ -678,11 +667,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 +681,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 +727,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 +743,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 +767,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 +813,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 +829,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 +982,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 +998,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 +1059,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,16 +1162,15 @@ 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;
}
static void
_cleanup_failed_config(NMVpnConnection *self)
{
- NMVpnConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE(self);
-
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip4_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip6_config);
_LOGW("VPN connection: did not receive valid IP config information");
_set_vpn_state(self, STATE_FAILED, NM_ACTIVE_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, FALSE);
@@ -1243,10 +1215,10 @@ nm_vpn_connection_config_maybe_complete(NMVpnConnection *self, gboolean success)
return;
if (success) {
- if ((priv->has_ip4 && !priv->ip4_config) || (priv->has_ip6 && !priv->ip6_config)) {
- /* Need to wait for other config */
- return;
- }
+ //XXX if ((priv->has_ip4 && !priv->ip4_config) || (priv->has_ip6 && !priv->ip6_config)) {
+ //XXX /* Need to wait for other config */
+ //XXX return;
+ //XXX }
}
nm_clear_g_source(&priv->connect_timeout);
@@ -1286,26 +1258,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;
}
@@ -1356,19 +1325,15 @@ process_generic_config(NMVpnConnection *self, GVariant *dict)
_notify(self, PROP_BANNER);
}
- /* Proxy Config */
- g_clear_object(&priv->proxy_config);
- priv->proxy_config = nm_proxy_config_new();
-
- if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_PROXY_PAC, "&s", &str)) {
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
- nm_proxy_config_set_pac_url(priv->proxy_config, str);
- } else
- nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
+ //XXX if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_PROXY_PAC, "&s", &str)) {
+ //XXX nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_AUTO);
+ //XXX nm_proxy_config_set_pac_url(priv->proxy_config, str);
+ //XXX } else
+ //XXX nm_proxy_config_set_method(priv->proxy_config, NM_PROXY_CONFIG_METHOD_NONE);
- /* User overrides if any from the NMConnection's Proxy settings */
- nm_proxy_config_merge_setting(priv->proxy_config,
- nm_connection_get_setting_proxy(_get_applied_connection(self)));
+ //XXX /* User overrides if any from the NMConnection's Proxy settings */
+ //XXX nm_proxy_config_merge_setting(priv->proxy_config,
+ //XXX nm_connection_get_setting_proxy(_get_applied_connection(self)));
/* External world-visible address of the VPN server */
priv->ip4_external_gw = 0;
@@ -1377,7 +1342,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) {
@@ -1414,12 +1379,12 @@ nm_vpn_connection_config_get(NMVpnConnection *self, GVariant *dict)
priv->has_ip4 = FALSE;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_HAS_IP4, "b", &b))
priv->has_ip4 = b;
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip4_config);
priv->has_ip6 = FALSE;
if (g_variant_lookup(dict, NM_VPN_PLUGIN_CONFIG_HAS_IP6, "b", &b))
priv->has_ip6 = b;
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
+ //XXX nm_dbus_object_clear_and_unexport(&priv->ip6_config);
nm_vpn_connection_config_maybe_complete(self, TRUE);
}
@@ -1486,20 +1451,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 +1501,15 @@ 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_IP_CONFIG_SOURCE_VPN);
- memset(&address, 0, sizeof(address));
- address.plen = 24;
+ nm_l3_config_data_set_dns_priority(l3cd, AF_INET, NM_DNS_PRIORITY_DEFAULT_VPN);
+
+ 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 +1528,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 +1551,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 +1567,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 +1609,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 +1623,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 +1642,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 +1706,20 @@ 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_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 +1738,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 +1750,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 +1760,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 +1775,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;
- memset(&route, 0, sizeof(route));
+ if (prefix > 128)
+ continue;
- if (!ip6_addr_from_variant(dest, &route.network))
- goto next;
+ route = (NMPlatformIP6Route){
+ .plen = prefix,
+ .table_coerced = nm_platform_route_table_coerce(route_table),
+ .metric = route_metric,
+ .rt_source = NM_IP_CONFIG_SOURCE_VPN,
+ };
- if (prefix > 128)
- goto next;
+ if (!ip6_addr_from_variant(dest, &route.network))
+ 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 +1820,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 +1832,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 +1849,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);
}
@@ -2423,28 +2414,12 @@ nm_vpn_connection_get_banner(NMVpnConnection *self)
return NM_VPN_CONNECTION_GET_PRIVATE(self)->banner;
}
-NMProxyConfig *
-nm_vpn_connection_get_proxy_config(NMVpnConnection *self)
+const NML3ConfigData *
+nm_vpn_connection_get_l3cd(NMVpnConnection *self, int addr_family)
{
g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->proxy_config;
-}
-
-NMIP4Config *
-nm_vpn_connection_get_ip4_config(NMVpnConnection *self)
-{
- g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
-
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->ip4_config;
-}
-
-NMIP6Config *
-nm_vpn_connection_get_ip6_config(NMVpnConnection *self)
-{
- g_return_val_if_fail(NM_IS_VPN_CONNECTION(self), NULL);
-
- return NM_VPN_CONNECTION_GET_PRIVATE(self)->ip6_config;
+ return NM_VPN_CONNECTION_GET_PRIVATE(self)->l3cd_x[NM_IS_IPv4(addr_family)];
}
static int
@@ -2820,8 +2795,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);
@@ -2830,9 +2803,6 @@ dispose(GObject *object)
nm_clear_g_cancellable(&priv->cancellable);
- g_clear_object(&priv->proxy_config);
- nm_dbus_object_clear_and_unexport(&priv->ip4_config);
- nm_dbus_object_clear_and_unexport(&priv->ip6_config);
g_clear_object(&priv->proxy);
g_clear_object(&priv->plugin_info);
@@ -2859,7 +2829,8 @@ finalize(GObject *object)
g_clear_object(&priv->netns);
}
-static gboolean
+//XXX
+_nm_unused static gboolean
ip_config_valid(VpnState state)
{
return (state == STATE_PRE_UP || state == STATE_ACTIVATED);
@@ -2879,14 +2850,14 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
g_value_set_string(value, priv->banner ?: "");
break;
case PROP_IP4_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->vpn_state) ? priv->ip4_config
- : NULL);
+ //XXX nm_dbus_utils_g_value_set_object_path(value,
+ //XXX ip_config_valid(priv->vpn_state) ? priv->ip4_config
+ //XXX : NULL);
break;
case PROP_IP6_CONFIG:
- nm_dbus_utils_g_value_set_object_path(value,
- ip_config_valid(priv->vpn_state) ? priv->ip6_config
- : NULL);
+ //XXX nm_dbus_utils_g_value_set_object_path(value,
+ //XXX ip_config_valid(priv->vpn_state) ? priv->ip6_config
+ //XXX : NULL);
break;
case PROP_MASTER:
parent_dev = nm_active_connection_get_device(NM_ACTIVE_CONNECTION(object));
diff --git a/src/core/vpn/nm-vpn-connection.h b/src/core/vpn/nm-vpn-connection.h
index 0209ea3d60..940a20d7a3 100644
--- a/src/core/vpn/nm-vpn-connection.h
+++ b/src/core/vpn/nm-vpn-connection.h
@@ -54,10 +54,8 @@ void nm_vpn_connection_disconnect(NMVpnConnection * self,
NMActiveConnectionStateReason reason,
gboolean quitting);
-NMProxyConfig *nm_vpn_connection_get_proxy_config(NMVpnConnection *self);
+const NML3ConfigData *nm_vpn_connection_get_l3cd(NMVpnConnection *self, int addr_family);
-NMIP4Config * nm_vpn_connection_get_ip4_config(NMVpnConnection *self);
-NMIP6Config * nm_vpn_connection_get_ip6_config(NMVpnConnection *self);
const char * nm_vpn_connection_get_ip_iface(NMVpnConnection *self, gboolean fallback_device);
int nm_vpn_connection_get_ip_ifindex(NMVpnConnection *self, gboolean fallback_device);
guint32 nm_vpn_connection_get_ip4_internal_gateway(NMVpnConnection *self);
diff --git a/src/libnm-systemd-core/meson.build b/src/libnm-systemd-core/meson.build
index 7ecf31640a..66e7cc82c4 100644
--- a/src/libnm-systemd-core/meson.build
+++ b/src/libnm-systemd-core/meson.build
@@ -18,8 +18,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/libnm-systemd-core/nm-sd.h b/src/libnm-systemd-core/nm-sd.h
index f346197440..c52f7cfe77 100644
--- a/src/libnm-systemd-core/nm-sd.h
+++ b/src/libnm-systemd-core/nm-sd.h
@@ -9,7 +9,6 @@
#include "src/systemd/sd-dhcp-client.h"
#include "src/systemd/sd-dhcp6-client.h"
#include "src/systemd/sd-lldp.h"
-#include "src/systemd/sd-ipv4ll.h"
/*****************************************************************************/
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' | \