diff options
| author | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-02-11 18:11:46 +0100 |
| commit | 80ec1decc49c72efec2a8b87c06245c92c0ab807 (patch) | |
| tree | e3b229aa94e8dcf0590f2317664176e7b8f7607b /src | |
| parent | 65f86e8f56267192d42f2b629fc6b0c99fb9cd0c (diff) | |
New upstream version 1.29.90 upstream/1.29.90
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/NetworkManagerUtils.c (renamed from src/NetworkManagerUtils.c) | 259 | ||||
| -rw-r--r-- | src/core/NetworkManagerUtils.h (renamed from src/NetworkManagerUtils.h) | 29 | ||||
| -rw-r--r-- | src/core/devices/adsl/meson.build (renamed from src/devices/adsl/meson.build) | 19 | ||||
| -rw-r--r-- | src/core/devices/adsl/nm-atm-manager.c (renamed from src/devices/adsl/nm-atm-manager.c) | 10 | ||||
| -rw-r--r-- | src/core/devices/adsl/nm-device-adsl.c (renamed from src/devices/adsl/nm-device-adsl.c) | 34 | ||||
| -rw-r--r-- | src/core/devices/adsl/nm-device-adsl.h (renamed from src/devices/adsl/nm-device-adsl.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/meson.build | 61 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bluez-common.h (renamed from src/devices/bluetooth/nm-bluez-common.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bluez-manager.c (renamed from src/devices/bluetooth/nm-bluez-manager.c) | 7 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bluez-manager.h (renamed from src/devices/bluetooth/nm-bluez-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bluez5-dun.c (renamed from src/devices/bluetooth/nm-bluez5-dun.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bluez5-dun.h (renamed from src/devices/bluetooth/nm-bluez5-dun.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bt-error.c (renamed from src/devices/bluetooth/nm-bt-error.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-bt-error.h (renamed from src/devices/bluetooth/nm-bt-error.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-device-bt.c (renamed from src/devices/bluetooth/nm-device-bt.c) | 7 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/nm-device-bt.h (renamed from src/devices/bluetooth/nm-device-bt.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/bluetooth/tests/nm-bt-test.c (renamed from src/devices/bluetooth/tests/nm-bt-test.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/meson.build (renamed from src/devices/meson.build) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-acd-manager.c (renamed from src/devices/nm-acd-manager.c) | 5 | ||||
| -rw-r--r-- | src/core/devices/nm-acd-manager.h (renamed from src/devices/nm-acd-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-6lowpan.c (renamed from src/devices/nm-device-6lowpan.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/nm-device-6lowpan.h (renamed from src/devices/nm-device-6lowpan.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bond.c (renamed from src/devices/nm-device-bond.c) | 46 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bond.h (renamed from src/devices/nm-device-bond.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bridge.c (renamed from src/devices/nm-device-bridge.c) | 33 | ||||
| -rw-r--r-- | src/core/devices/nm-device-bridge.h (renamed from src/devices/nm-device-bridge.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-dummy.c (renamed from src/devices/nm-device-dummy.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/nm-device-dummy.h (renamed from src/devices/nm-device-dummy.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ethernet-utils.c (renamed from src/devices/nm-device-ethernet-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ethernet-utils.h (renamed from src/devices/nm-device-ethernet-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ethernet.c (renamed from src/devices/nm-device-ethernet.c) | 113 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ethernet.h (renamed from src/devices/nm-device-ethernet.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-factory.c (renamed from src/devices/nm-device-factory.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/nm-device-factory.h (renamed from src/devices/nm-device-factory.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-generic.c (renamed from src/devices/nm-device-generic.c) | 24 | ||||
| -rw-r--r-- | src/core/devices/nm-device-generic.h (renamed from src/devices/nm-device-generic.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-infiniband.c (renamed from src/devices/nm-device-infiniband.c) | 30 | ||||
| -rw-r--r-- | src/core/devices/nm-device-infiniband.h (renamed from src/devices/nm-device-infiniband.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ip-tunnel.c (renamed from src/devices/nm-device-ip-tunnel.c) | 31 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ip-tunnel.h (renamed from src/devices/nm-device-ip-tunnel.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-logging.h (renamed from src/devices/nm-device-logging.h) | 65 | ||||
| -rw-r--r-- | src/core/devices/nm-device-macsec.c (renamed from src/devices/nm-device-macsec.c) | 28 | ||||
| -rw-r--r-- | src/core/devices/nm-device-macsec.h (renamed from src/devices/nm-device-macsec.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-macvlan.c (renamed from src/devices/nm-device-macvlan.c) | 30 | ||||
| -rw-r--r-- | src/core/devices/nm-device-macvlan.h (renamed from src/devices/nm-device-macvlan.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ppp.c (renamed from src/devices/nm-device-ppp.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/nm-device-ppp.h (renamed from src/devices/nm-device-ppp.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-private.h (renamed from src/devices/nm-device-private.h) | 8 | ||||
| -rw-r--r-- | src/core/devices/nm-device-tun.c (renamed from src/devices/nm-device-tun.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/nm-device-tun.h (renamed from src/devices/nm-device-tun.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-veth.c (renamed from src/devices/nm-device-veth.c) | 96 | ||||
| -rw-r--r-- | src/core/devices/nm-device-veth.h (renamed from src/devices/nm-device-veth.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vlan.c (renamed from src/devices/nm-device-vlan.c) | 32 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vlan.h (renamed from src/devices/nm-device-vlan.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vrf.c (renamed from src/devices/nm-device-vrf.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vrf.h (renamed from src/devices/nm-device-vrf.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vxlan.c (renamed from src/devices/nm-device-vxlan.c) | 72 | ||||
| -rw-r--r-- | src/core/devices/nm-device-vxlan.h (renamed from src/devices/nm-device-vxlan.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-wireguard.c (renamed from src/devices/nm-device-wireguard.c) | 135 | ||||
| -rw-r--r-- | src/core/devices/nm-device-wireguard.h (renamed from src/devices/nm-device-wireguard.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device-wpan.c (renamed from src/devices/nm-device-wpan.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/nm-device-wpan.h (renamed from src/devices/nm-device-wpan.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/nm-device.c (renamed from src/devices/nm-device.c) | 1524 | ||||
| -rw-r--r-- | src/core/devices/nm-device.h (renamed from src/devices/nm-device.h) | 36 | ||||
| -rw-r--r-- | src/core/devices/nm-lldp-listener.c (renamed from src/devices/nm-lldp-listener.c) | 10 | ||||
| -rw-r--r-- | src/core/devices/nm-lldp-listener.h (renamed from src/devices/nm-lldp-listener.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/ovs/meson.build | 32 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-bridge.c (renamed from src/devices/ovs/nm-device-ovs-bridge.c) | 61 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-bridge.h (renamed from src/devices/ovs/nm-device-ovs-bridge.h) | 7 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-interface.c (renamed from src/devices/ovs/nm-device-ovs-interface.c) | 87 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-interface.h (renamed from src/devices/ovs/nm-device-ovs-interface.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-port.c (renamed from src/devices/ovs/nm-device-ovs-port.c) | 24 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-device-ovs-port.h (renamed from src/devices/ovs/nm-device-ovs-port.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovs-factory.c (renamed from src/devices/ovs/nm-ovs-factory.c) | 79 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovsdb.c (renamed from src/devices/ovs/nm-ovsdb.c) | 1636 | ||||
| -rw-r--r-- | src/core/devices/ovs/nm-ovsdb.h (renamed from src/devices/ovs/nm-ovsdb.h) | 14 | ||||
| -rw-r--r-- | src/core/devices/team/meson.build (renamed from src/devices/team/meson.build) | 29 | ||||
| -rw-r--r-- | src/core/devices/team/nm-device-team.c (renamed from src/devices/team/nm-device-team.c) | 30 | ||||
| -rw-r--r-- | src/core/devices/team/nm-device-team.h (renamed from src/devices/team/nm-device-team.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/team/nm-team-factory.c (renamed from src/devices/team/nm-team-factory.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/tests/meson.build (renamed from src/devices/tests/meson.build) | 4 | ||||
| -rw-r--r-- | src/core/devices/tests/test-acd.c (renamed from src/devices/tests/test-acd.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/tests/test-lldp.c (renamed from src/devices/tests/test-lldp.c) | 30 | ||||
| -rw-r--r-- | src/core/devices/wifi/meson.build (renamed from src/devices/wifi/meson.build) | 24 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-iwd.c (renamed from src/devices/wifi/nm-device-iwd.c) | 1472 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-iwd.h (renamed from src/devices/wifi/nm-device-iwd.h) | 4 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-olpc-mesh.c (renamed from src/devices/wifi/nm-device-olpc-mesh.c) | 26 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-olpc-mesh.h (renamed from src/devices/wifi/nm-device-olpc-mesh.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-wifi-p2p.c (renamed from src/devices/wifi/nm-device-wifi-p2p.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-wifi-p2p.h (renamed from src/devices/wifi/nm-device-wifi-p2p.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-wifi.c (renamed from src/devices/wifi/nm-device-wifi.c) | 94 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-device-wifi.h (renamed from src/devices/wifi/nm-device-wifi.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-iwd-manager.c (renamed from src/devices/wifi/nm-iwd-manager.c) | 707 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-iwd-manager.h (renamed from src/devices/wifi/nm-iwd-manager.h) | 5 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-ap.c (renamed from src/devices/wifi/nm-wifi-ap.c) | 68 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-ap.h (renamed from src/devices/wifi/nm-wifi-ap.h) | 38 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-common.c (renamed from src/devices/wifi/nm-wifi-common.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-common.h (renamed from src/devices/wifi/nm-wifi-common.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-factory.c (renamed from src/devices/wifi/nm-wifi-factory.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-p2p-peer.c (renamed from src/devices/wifi/nm-wifi-p2p-peer.c) | 7 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-p2p-peer.h (renamed from src/devices/wifi/nm-wifi-p2p-peer.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-utils.c (renamed from src/devices/wifi/nm-wifi-utils.c) | 68 | ||||
| -rw-r--r-- | src/core/devices/wifi/nm-wifi-utils.h (renamed from src/devices/wifi/nm-wifi-utils.h) | 9 | ||||
| -rw-r--r-- | src/core/devices/wifi/tests/test-devices-wifi.c (renamed from src/devices/wifi/tests/test-devices-wifi.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wwan/libnm-wwan.ver (renamed from src/devices/wwan/libnm-wwan.ver) | 0 | ||||
| -rw-r--r-- | src/core/devices/wwan/meson.build (renamed from src/devices/wwan/meson.build) | 70 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-device-modem.c (renamed from src/devices/wwan/nm-device-modem.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-device-modem.h (renamed from src/devices/wwan/nm-device-modem.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-broadband.c (renamed from src/devices/wwan/nm-modem-broadband.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-broadband.h (renamed from src/devices/wwan/nm-modem-broadband.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-manager.c (renamed from src/devices/wwan/nm-modem-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-manager.h (renamed from src/devices/wwan/nm-modem-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-ofono.c (renamed from src/devices/wwan/nm-modem-ofono.c) | 32 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem-ofono.h (renamed from src/devices/wwan/nm-modem-ofono.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem.c (renamed from src/devices/wwan/nm-modem.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-modem.h (renamed from src/devices/wwan/nm-modem.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-service-providers.c (renamed from src/devices/wwan/nm-service-providers.c) | 4 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-service-providers.h (renamed from src/devices/wwan/nm-service-providers.h) | 2 | ||||
| -rw-r--r-- | src/core/devices/wwan/nm-wwan-factory.c (renamed from src/devices/wwan/nm-wwan-factory.c) | 6 | ||||
| -rw-r--r-- | src/core/devices/wwan/tests/test-service-providers.c (renamed from src/devices/wwan/tests/test-service-providers.c) | 8 | ||||
| -rw-r--r-- | src/core/devices/wwan/tests/test-service-providers.xml (renamed from src/devices/wwan/tests/test-service-providers.xml) | 0 | ||||
| -rw-r--r-- | src/core/dhcp/meson.build | 18 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-client-logging.h (renamed from src/dhcp/nm-dhcp-client-logging.h) | 2 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-client.c (renamed from src/dhcp/nm-dhcp-client.c) | 55 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-client.h (renamed from src/dhcp/nm-dhcp-client.h) | 5 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-dhclient-utils.c (renamed from src/dhcp/nm-dhcp-dhclient-utils.c) | 5 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-dhclient-utils.h (renamed from src/dhcp/nm-dhcp-dhclient-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-dhclient.c (renamed from src/dhcp/nm-dhcp-dhclient.c) | 10 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-dhcpcanon.c (renamed from src/dhcp/nm-dhcp-dhcpcanon.c) | 4 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-dhcpcd.c (renamed from src/dhcp/nm-dhcp-dhcpcd.c) | 86 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-helper-api.h (renamed from src/dhcp/nm-dhcp-helper-api.h) | 2 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-helper.c (renamed from src/dhcp/nm-dhcp-helper.c) | 4 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-listener.c (renamed from src/dhcp/nm-dhcp-listener.c) | 4 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-listener.h (renamed from src/dhcp/nm-dhcp-listener.h) | 2 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-manager.c (renamed from src/dhcp/nm-dhcp-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-manager.h (renamed from src/dhcp/nm-dhcp-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-nettools.c (renamed from src/dhcp/nm-dhcp-nettools.c) | 912 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-options.c (renamed from src/dhcp/nm-dhcp-options.c) | 272 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-options.h (renamed from src/dhcp/nm-dhcp-options.h) | 55 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-systemd.c (renamed from src/dhcp/nm-dhcp-systemd.c) | 134 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-utils.c (renamed from src/dhcp/nm-dhcp-utils.c) | 289 | ||||
| -rw-r--r-- | src/core/dhcp/nm-dhcp-utils.h (renamed from src/dhcp/nm-dhcp-utils.h) | 33 | ||||
| -rw-r--r-- | src/core/dhcp/tests/meson.build (renamed from src/dhcp/tests/meson.build) | 4 | ||||
| -rw-r--r-- | src/core/dhcp/tests/test-dhclient-commented-duid.leases (renamed from src/dhcp/tests/test-dhclient-commented-duid.leases) | 0 | ||||
| -rw-r--r-- | src/core/dhcp/tests/test-dhclient-duid.leases (renamed from src/dhcp/tests/test-dhclient-duid.leases) | 0 | ||||
| -rw-r--r-- | src/core/dhcp/tests/test-dhcp-dhclient.c (renamed from src/dhcp/tests/test-dhcp-dhclient.c) | 6 | ||||
| -rw-r--r-- | src/core/dhcp/tests/test-dhcp-utils.c (renamed from src/dhcp/tests/test-dhcp-utils.c) | 57 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-dnsmasq.c (renamed from src/dns/nm-dns-dnsmasq.c) | 8 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-dnsmasq.h (renamed from src/dns/nm-dns-dnsmasq.h) | 2 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-manager.c (renamed from src/dns/nm-dns-manager.c) | 277 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-manager.h (renamed from src/dns/nm-dns-manager.h) | 9 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-plugin.c (renamed from src/dns/nm-dns-plugin.c) | 4 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-plugin.h (renamed from src/dns/nm-dns-plugin.h) | 4 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-systemd-resolved.c (renamed from src/dns/nm-dns-systemd-resolved.c) | 10 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-systemd-resolved.h (renamed from src/dns/nm-dns-systemd-resolved.h) | 2 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-unbound.c (renamed from src/dns/nm-dns-unbound.c) | 4 | ||||
| -rw-r--r-- | src/core/dns/nm-dns-unbound.h (renamed from src/dns/nm-dns-unbound.h) | 2 | ||||
| -rw-r--r-- | src/core/dnsmasq/nm-dnsmasq-manager.c (renamed from src/dnsmasq/nm-dnsmasq-manager.c) | 6 | ||||
| -rw-r--r-- | src/core/dnsmasq/nm-dnsmasq-manager.h (renamed from src/dnsmasq/nm-dnsmasq-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/dnsmasq/nm-dnsmasq-utils.c (renamed from src/dnsmasq/nm-dnsmasq-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/dnsmasq/nm-dnsmasq-utils.h (renamed from src/dnsmasq/nm-dnsmasq-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/dnsmasq/tests/meson.build (renamed from src/dnsmasq/tests/meson.build) | 4 | ||||
| -rw-r--r-- | src/core/dnsmasq/tests/test-dnsmasq-utils.c (renamed from src/dnsmasq/tests/test-dnsmasq-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/initrd/meson.build | 31 | ||||
| -rw-r--r-- | src/core/initrd/nm-initrd-generator.c (renamed from src/initrd/nm-initrd-generator.c) | 78 | ||||
| -rw-r--r-- | src/core/initrd/nm-initrd-generator.h (renamed from src/initrd/nm-initrd-generator.h) | 8 | ||||
| -rw-r--r-- | src/core/initrd/nmi-cmdline-reader.c (renamed from src/initrd/nmi-cmdline-reader.c) | 75 | ||||
| -rw-r--r-- | src/core/initrd/nmi-dt-reader.c (renamed from src/initrd/nmi-dt-reader.c) | 5 | ||||
| -rw-r--r-- | src/core/initrd/nmi-ibft-reader.c (renamed from src/initrd/nmi-ibft-reader.c) | 5 | ||||
| -rw-r--r-- | src/core/initrd/tests/meson.build (renamed from src/initrd/tests/meson.build) | 8 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address (renamed from src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address (renamed from src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address (renamed from src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address (renamed from src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address (renamed from src/initrd/tests/sysfs-dhcp/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address (renamed from src/initrd/tests/sysfs-dhcp/class/net/eth1/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name (renamed from src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath (renamed from src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath) | bin | 108 -> 108 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request) | bin | 273 -> 273 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response) | bin | 300 -> 300 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath) | bin | 37 -> 37 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name) | bin | 9 -> 9 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name) | bin | 15 -> 15 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name) | bin | 7 -> 7 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip) | bin | 4 -> 4 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path) | bin | 1 -> 1 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file) | bin | 11 -> 11 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options) | bin | 1 -> 1 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type) | bin | 8 -> 8 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name (renamed from src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name) | bin | 9 -> 9 bytes | |||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/class/net/eth0/address (renamed from src/initrd/tests/sysfs-static/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/class/net/eth1/address (renamed from src/initrd/tests/sysfs-static/class/net/eth1/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan (renamed from src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target1/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target1/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target1/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name (renamed from src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/class/net/eth0/address (renamed from src/initrd/tests/sysfs-vlan/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name (renamed from src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/class/net/eth0/address (renamed from src/initrd/tests/sysfs/class/net/eth0/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/class/net/eth2/address (renamed from src/initrd/tests/sysfs/class/net/eth2/address) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id (renamed from src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id (renamed from src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature (renamed from src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan (renamed from src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/flags) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/index (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server (renamed from src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/chap-type) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/flags (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/flags) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/index (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/lun (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target0/port (renamed from src/initrd/tests/sysfs/firmware/ibft/target0/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/chap-type) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/flags (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/flags) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/index (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/index) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/lun (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/lun) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/port (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/port) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name (renamed from src/initrd/tests/sysfs/firmware/ibft/target2/target-name) | 0 | ||||
| -rw-r--r-- | src/core/initrd/tests/test-cmdline-reader.c (renamed from src/initrd/tests/test-cmdline-reader.c) | 670 | ||||
| -rw-r--r-- | src/core/initrd/tests/test-dt-reader.c (renamed from src/initrd/tests/test-dt-reader.c) | 9 | ||||
| -rw-r--r-- | src/core/initrd/tests/test-ibft-reader.c (renamed from src/initrd/tests/test-ibft-reader.c) | 9 | ||||
| -rw-r--r-- | src/core/main-utils.c (renamed from src/main-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/main-utils.h (renamed from src/main-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/main.c (renamed from src/main.c) | 9 | ||||
| -rw-r--r-- | src/core/meson.build | 333 | ||||
| -rw-r--r-- | src/core/ndisc/nm-fake-ndisc.c (renamed from src/ndisc/nm-fake-ndisc.c) | 144 | ||||
| -rw-r--r-- | src/core/ndisc/nm-fake-ndisc.h (renamed from src/ndisc/nm-fake-ndisc.h) | 16 | ||||
| -rw-r--r-- | src/core/ndisc/nm-lndp-ndisc.c (renamed from src/ndisc/nm-lndp-ndisc.c) | 348 | ||||
| -rw-r--r-- | src/core/ndisc/nm-lndp-ndisc.h (renamed from src/ndisc/nm-lndp-ndisc.h) | 2 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc-private.h (renamed from src/ndisc/nm-ndisc-private.h) | 15 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc.c (renamed from src/ndisc/nm-ndisc.c) | 902 | ||||
| -rw-r--r-- | src/core/ndisc/nm-ndisc.h (renamed from src/ndisc/nm-ndisc.h) | 117 | ||||
| -rw-r--r-- | src/core/ndisc/tests/meson.build (renamed from src/ndisc/tests/meson.build) | 6 | ||||
| -rw-r--r-- | src/core/ndisc/tests/test-ndisc-fake.c | 657 | ||||
| -rw-r--r-- | src/core/ndisc/tests/test-ndisc-linux.c (renamed from src/ndisc/tests/test-ndisc-linux.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-act-request.c (renamed from src/nm-act-request.c) | 160 | ||||
| -rw-r--r-- | src/core/nm-act-request.h (renamed from src/nm-act-request.h) | 12 | ||||
| -rw-r--r-- | src/core/nm-active-connection.c (renamed from src/nm-active-connection.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-active-connection.h (renamed from src/nm-active-connection.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-audit-manager.c (renamed from src/nm-audit-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-audit-manager.h (renamed from src/nm-audit-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-auth-manager.c (renamed from src/nm-auth-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-auth-manager.h (renamed from src/nm-auth-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-auth-utils.c (renamed from src/nm-auth-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-auth-utils.h (renamed from src/nm-auth-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-checkpoint-manager.c (renamed from src/nm-checkpoint-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-checkpoint-manager.h (renamed from src/nm-checkpoint-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-checkpoint.c (renamed from src/nm-checkpoint.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-checkpoint.h (renamed from src/nm-checkpoint.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-config-data.c (renamed from src/nm-config-data.c) | 16 | ||||
| -rw-r--r-- | src/core/nm-config-data.h (renamed from src/nm-config-data.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-config.c (renamed from src/nm-config.c) | 9 | ||||
| -rw-r--r-- | src/core/nm-config.h (renamed from src/nm-config.h) | 3 | ||||
| -rw-r--r-- | src/core/nm-connectivity.c (renamed from src/nm-connectivity.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-connectivity.h (renamed from src/nm-connectivity.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-core-utils.c (renamed from src/nm-core-utils.c) | 106 | ||||
| -rw-r--r-- | src/core/nm-core-utils.h (renamed from src/nm-core-utils.h) | 31 | ||||
| -rw-r--r-- | src/core/nm-dbus-manager.c (renamed from src/nm-dbus-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-dbus-manager.h (renamed from src/nm-dbus-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-dbus-object.c (renamed from src/nm-dbus-object.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-dbus-object.h (renamed from src/nm-dbus-object.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-dbus-utils.c (renamed from src/nm-dbus-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-dbus-utils.h (renamed from src/nm-dbus-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-dcb.c (renamed from src/nm-dcb.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-dcb.h (renamed from src/nm-dcb.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-default-daemon.h | 26 | ||||
| -rw-r--r-- | src/core/nm-dhcp-config.c (renamed from src/nm-dhcp-config.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-dhcp-config.h (renamed from src/nm-dhcp-config.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-dispatcher.c (renamed from src/nm-dispatcher.c) | 241 | ||||
| -rw-r--r-- | src/core/nm-dispatcher.h (renamed from src/nm-dispatcher.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-firewall-manager.c (renamed from src/nm-firewall-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-firewall-manager.h (renamed from src/nm-firewall-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-hostname-manager.c (renamed from src/nm-hostname-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-hostname-manager.h (renamed from src/nm-hostname-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-iface-helper.c (renamed from src/nm-iface-helper.c) | 6 | ||||
| -rw-r--r-- | src/core/nm-ip-config.c (renamed from src/nm-ip-config.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-ip-config.h (renamed from src/nm-ip-config.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-ip4-config.c (renamed from src/nm-ip4-config.c) | 22 | ||||
| -rw-r--r-- | src/core/nm-ip4-config.h (renamed from src/nm-ip4-config.h) | 64 | ||||
| -rw-r--r-- | src/core/nm-ip6-config.c (renamed from src/nm-ip6-config.c) | 45 | ||||
| -rw-r--r-- | src/core/nm-ip6-config.h (renamed from src/nm-ip6-config.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-keep-alive.c (renamed from src/nm-keep-alive.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-keep-alive.h (renamed from src/nm-keep-alive.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-l3-config-data.c (renamed from src/nm-l3-config-data.c) | 95 | ||||
| -rw-r--r-- | src/core/nm-l3-config-data.h (renamed from src/nm-l3-config-data.h) | 15 | ||||
| -rw-r--r-- | src/core/nm-l3-ipv4ll.c | 1059 | ||||
| -rw-r--r-- | src/core/nm-l3-ipv4ll.h | 118 | ||||
| -rw-r--r-- | src/core/nm-l3cfg.c (renamed from src/nm-l3cfg.c) | 2335 | ||||
| -rw-r--r-- | src/core/nm-l3cfg.h (renamed from src/nm-l3cfg.h) | 106 | ||||
| -rw-r--r-- | src/core/nm-manager.c (renamed from src/nm-manager.c) | 106 | ||||
| -rw-r--r-- | src/core/nm-manager.h (renamed from src/nm-manager.h) | 23 | ||||
| -rw-r--r-- | src/core/nm-netns.c (renamed from src/nm-netns.c) | 21 | ||||
| -rw-r--r-- | src/core/nm-netns.h (renamed from src/nm-netns.h) | 6 | ||||
| -rw-r--r-- | src/core/nm-pacrunner-manager.c (renamed from src/nm-pacrunner-manager.c) | 67 | ||||
| -rw-r--r-- | src/core/nm-pacrunner-manager.h (renamed from src/nm-pacrunner-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-policy.c (renamed from src/nm-policy.c) | 418 | ||||
| -rw-r--r-- | src/core/nm-policy.h (renamed from src/nm-policy.h) | 4 | ||||
| -rw-r--r-- | src/core/nm-proxy-config.c (renamed from src/nm-proxy-config.c) | 6 | ||||
| -rw-r--r-- | src/core/nm-proxy-config.h (renamed from src/nm-proxy-config.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-rfkill-manager.c (renamed from src/nm-rfkill-manager.c) | 10 | ||||
| -rw-r--r-- | src/core/nm-rfkill-manager.h (renamed from src/nm-rfkill-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-session-monitor.c (renamed from src/nm-session-monitor.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-session-monitor.h (renamed from src/nm-session-monitor.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-sleep-monitor.c (renamed from src/nm-sleep-monitor.c) | 4 | ||||
| -rw-r--r-- | src/core/nm-sleep-monitor.h (renamed from src/nm-sleep-monitor.h) | 2 | ||||
| -rw-r--r-- | src/core/nm-test-utils-core.h (renamed from src/nm-test-utils-core.h) | 4 | ||||
| -rw-r--r-- | src/core/nm-types.h (renamed from src/nm-types.h) | 38 | ||||
| -rw-r--r-- | src/core/org.freedesktop.NetworkManager.conf (renamed from src/org.freedesktop.NetworkManager.conf) | 0 | ||||
| -rw-r--r-- | src/core/platform/linux/nl802154.h (renamed from src/platform/linux/nl802154.h) | 0 | ||||
| -rw-r--r-- | src/core/platform/nm-fake-platform.c (renamed from src/platform/nm-fake-platform.c) | 6 | ||||
| -rw-r--r-- | src/core/platform/nm-fake-platform.h (renamed from src/platform/nm-fake-platform.h) | 2 | ||||
| -rw-r--r-- | src/core/platform/nm-linux-platform.c (renamed from src/platform/nm-linux-platform.c) | 65 | ||||
| -rw-r--r-- | src/core/platform/nm-linux-platform.h (renamed from src/platform/nm-linux-platform.h) | 2 | ||||
| -rw-r--r-- | src/core/platform/nm-platform-private.h (renamed from src/platform/nm-platform-private.h) | 2 | ||||
| -rw-r--r-- | src/core/platform/nm-platform.c (renamed from src/platform/nm-platform.c) | 150 | ||||
| -rw-r--r-- | src/core/platform/nm-platform.h (renamed from src/platform/nm-platform.h) | 186 | ||||
| -rw-r--r-- | src/core/platform/nmp-object.c (renamed from src/platform/nmp-object.c) | 14 | ||||
| -rw-r--r-- | src/core/platform/nmp-object.h (renamed from src/platform/nmp-object.h) | 106 | ||||
| -rw-r--r-- | src/core/platform/nmp-rules-manager.c (renamed from src/platform/nmp-rules-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/platform/nmp-rules-manager.h (renamed from src/platform/nmp-rules-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/platform/tests/meson.build (renamed from src/platform/tests/meson.build) | 6 | ||||
| -rw-r--r-- | src/core/platform/tests/monitor.c (renamed from src/platform/tests/monitor.c) | 4 | ||||
| -rw-r--r-- | src/core/platform/tests/test-address.c (renamed from src/platform/tests/test-address.c) | 4 | ||||
| -rw-r--r-- | src/core/platform/tests/test-cleanup.c (renamed from src/platform/tests/test-cleanup.c) | 4 | ||||
| -rw-r--r-- | src/core/platform/tests/test-common.c (renamed from src/platform/tests/test-common.c) | 192 | ||||
| -rw-r--r-- | src/core/platform/tests/test-common.h (renamed from src/platform/tests/test-common.h) | 11 | ||||
| -rw-r--r-- | src/core/platform/tests/test-link.c (renamed from src/platform/tests/test-link.c) | 28 | ||||
| -rw-r--r-- | src/core/platform/tests/test-nmp-object.c (renamed from src/platform/tests/test-nmp-object.c) | 8 | ||||
| -rw-r--r-- | src/core/platform/tests/test-platform-general.c (renamed from src/platform/tests/test-platform-general.c) | 6 | ||||
| -rw-r--r-- | src/core/platform/tests/test-route.c (renamed from src/platform/tests/test-route.c) | 6 | ||||
| -rw-r--r-- | src/core/platform/tests/test-tc.c (renamed from src/platform/tests/test-tc.c) | 8 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils-nl80211.c (renamed from src/platform/wifi/nm-wifi-utils-nl80211.c) | 291 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils-nl80211.h (renamed from src/platform/wifi/nm-wifi-utils-nl80211.h) | 4 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils-private.h (renamed from src/platform/wifi/nm-wifi-utils-private.h) | 20 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils-wext.c (renamed from src/platform/wifi/nm-wifi-utils-wext.c) | 45 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils-wext.h (renamed from src/platform/wifi/nm-wifi-utils-wext.h) | 2 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils.c (renamed from src/platform/wifi/nm-wifi-utils.c) | 29 | ||||
| -rw-r--r-- | src/core/platform/wifi/nm-wifi-utils.h (renamed from src/platform/wifi/nm-wifi-utils.h) | 23 | ||||
| -rw-r--r-- | src/core/platform/wpan/nm-wpan-utils.c (renamed from src/platform/wpan/nm-wpan-utils.c) | 8 | ||||
| -rw-r--r-- | src/core/platform/wpan/nm-wpan-utils.h (renamed from src/platform/wpan/nm-wpan-utils.h) | 4 | ||||
| -rw-r--r-- | src/core/ppp/meson.build (renamed from src/ppp/meson.build) | 27 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-manager-call.c (renamed from src/ppp/nm-ppp-manager-call.c) | 4 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-manager-call.h (renamed from src/ppp/nm-ppp-manager-call.h) | 2 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-manager.c (renamed from src/ppp/nm-ppp-manager.c) | 7 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-manager.h (renamed from src/ppp/nm-ppp-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-plugin-api.h (renamed from src/ppp/nm-ppp-plugin-api.h) | 2 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-plugin.ver (renamed from src/ppp/nm-ppp-plugin.ver) | 0 | ||||
| -rw-r--r-- | src/core/ppp/nm-ppp-status.h (renamed from src/ppp/nm-ppp-status.h) | 2 | ||||
| -rw-r--r-- | src/core/ppp/nm-pppd-plugin.c (renamed from src/ppp/nm-pppd-plugin.c) | 4 | ||||
| -rw-r--r-- | src/core/ppp/nm-pppd-plugin.h (renamed from src/ppp/nm-pppd-plugin.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-agent-manager.c (renamed from src/settings/nm-agent-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/nm-agent-manager.h (renamed from src/settings/nm-agent-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-secret-agent.c (renamed from src/settings/nm-secret-agent.c) | 6 | ||||
| -rw-r--r-- | src/core/settings/nm-secret-agent.h (renamed from src/settings/nm-secret-agent.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-connection.c (renamed from src/settings/nm-settings-connection.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-connection.h (renamed from src/settings/nm-settings-connection.h) | 6 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-plugin.c (renamed from src/settings/nm-settings-plugin.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-plugin.h (renamed from src/settings/nm-settings-plugin.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-storage.c (renamed from src/settings/nm-settings-storage.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-storage.h (renamed from src/settings/nm-settings-storage.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-utils.c (renamed from src/settings/nm-settings-utils.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/nm-settings-utils.h (renamed from src/settings/nm-settings-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/nm-settings.c (renamed from src/settings/nm-settings.c) | 14 | ||||
| -rw-r--r-- | src/core/settings/nm-settings.h (renamed from src/settings/nm-settings.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/meson.build (renamed from src/settings/plugins/ifcfg-rh/meson.build) | 46 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf (renamed from src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml (renamed from src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nm-ifdown (renamed from src/settings/plugins/ifcfg-rh/nm-ifdown) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nm-ifup (renamed from src/settings/plugins/ifcfg-rh/nm-ifup) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c) | 136 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c) | 21 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h) | 6 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c) | 34 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h (renamed from src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/shvar.c (renamed from src/settings/plugins/ifcfg-rh/shvar.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/shvar.h (renamed from src/settings/plugins/ifcfg-rh/shvar.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/meson.build | 16 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls | 22 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 (renamed from src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12) | bin | 2848 -> 2848 bytes | |||
| -rw-r--r-- | src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c (renamed from src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c) | 44 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/meson.build (renamed from src/settings/plugins/ifupdown/meson.build) | 16 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c (renamed from src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h (renamed from src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c (renamed from src/settings/plugins/ifupdown/nms-ifupdown-parser.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-parser.h (renamed from src/settings/plugins/ifupdown/nms-ifupdown-parser.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c (renamed from src/settings/plugins/ifupdown/nms-ifupdown-plugin.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.h (renamed from src/settings/plugins/ifupdown/nms-ifupdown-plugin.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/meson.build | 15 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test-ifupdown.c (renamed from src/settings/plugins/ifupdown/tests/test-ifupdown.c) | 6 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test1 (renamed from src/settings/plugins/ifupdown/tests/test1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test11 (renamed from src/settings/plugins/ifupdown/tests/test11) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test12 (renamed from src/settings/plugins/ifupdown/tests/test12) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test13 (renamed from src/settings/plugins/ifupdown/tests/test13) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test14 (renamed from src/settings/plugins/ifupdown/tests/test14) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test15 (renamed from src/settings/plugins/ifupdown/tests/test15) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test16 (renamed from src/settings/plugins/ifupdown/tests/test16) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4 (renamed from src/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 (renamed from src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen (renamed from src/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test2 (renamed from src/settings/plugins/ifupdown/tests/test2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test20-source-stanza (renamed from src/settings/plugins/ifupdown/tests/test20-source-stanza) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 (renamed from src/settings/plugins/ifupdown/tests/test20-source-stanza.eth0) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 (renamed from src/settings/plugins/ifupdown/tests/test20-source-stanza.eth1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza (renamed from src/settings/plugins/ifupdown/tests/test21-source-dir-stanza) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 (renamed from src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test22-duplicate-stanzas (renamed from src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test3 (renamed from src/settings/plugins/ifupdown/tests/test3) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test4 (renamed from src/settings/plugins/ifupdown/tests/test4) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test5 (renamed from src/settings/plugins/ifupdown/tests/test5) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test6 (renamed from src/settings/plugins/ifupdown/tests/test6) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test7 (renamed from src/settings/plugins/ifupdown/tests/test7) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test8 (renamed from src/settings/plugins/ifupdown/tests/test8) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/ifupdown/tests/test9 (renamed from src/settings/plugins/ifupdown/tests/test9) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-plugin.c (renamed from src/settings/plugins/keyfile/nms-keyfile-plugin.c) | 6 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-plugin.h (renamed from src/settings/plugins/keyfile/nms-keyfile-plugin.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-reader.c (renamed from src/settings/plugins/keyfile/nms-keyfile-reader.c) | 6 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-reader.h (renamed from src/settings/plugins/keyfile/nms-keyfile-reader.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-storage.c (renamed from src/settings/plugins/keyfile/nms-keyfile-storage.c) | 4 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-storage.h (renamed from src/settings/plugins/keyfile/nms-keyfile-storage.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-utils.c (renamed from src/settings/plugins/keyfile/nms-keyfile-utils.c) | 6 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-utils.h (renamed from src/settings/plugins/keyfile/nms-keyfile-utils.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-writer.c (renamed from src/settings/plugins/keyfile/nms-keyfile-writer.c) | 16 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/nms-keyfile-writer.h (renamed from src/settings/plugins/keyfile/nms-keyfile-writer.h) | 2 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT (renamed from src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain (renamed from src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 (renamed from src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem (renamed from src/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem (renamed from src/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem) | 0 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/meson.build | 15 | ||||
| -rw-r--r-- | src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c (renamed from src/settings/plugins/keyfile/tests/test-keyfile-settings.c) | 10 | ||||
| -rw-r--r-- | src/core/settings/plugins/meson.build (renamed from src/settings/plugins/meson.build) | 2 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-config.c (renamed from src/supplicant/nm-supplicant-config.c) | 53 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-config.h (renamed from src/supplicant/nm-supplicant-config.h) | 2 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-interface.c (renamed from src/supplicant/nm-supplicant-interface.c) | 71 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-interface.h (renamed from src/supplicant/nm-supplicant-interface.h) | 4 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-manager.c (renamed from src/supplicant/nm-supplicant-manager.c) | 9 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-manager.h (renamed from src/supplicant/nm-supplicant-manager.h) | 2 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-settings-verify.c (renamed from src/supplicant/nm-supplicant-settings-verify.c) | 9 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-settings-verify.h (renamed from src/supplicant/nm-supplicant-settings-verify.h) | 2 | ||||
| -rw-r--r-- | src/core/supplicant/nm-supplicant-types.h (renamed from src/supplicant/nm-supplicant-types.h) | 5 | ||||
| -rw-r--r-- | src/core/supplicant/tests/certs/test-ca-cert.pem (renamed from src/supplicant/tests/certs/test-ca-cert.pem) | 0 | ||||
| -rw-r--r-- | src/core/supplicant/tests/certs/test-cert.p12 (renamed from src/supplicant/tests/certs/test-cert.p12) | bin | 4092 -> 4092 bytes | |||
| -rw-r--r-- | src/core/supplicant/tests/meson.build (renamed from src/supplicant/tests/meson.build) | 4 | ||||
| -rw-r--r-- | src/core/supplicant/tests/test-supplicant-config.c (renamed from src/supplicant/tests/test-supplicant-config.c) | 92 | ||||
| -rw-r--r-- | src/core/systemd/meson.build | 62 | ||||
| -rw-r--r-- | src/core/systemd/nm-default-systemd.h | 18 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd-utils-core.c (renamed from src/systemd/nm-sd-utils-core.c) | 4 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd-utils-core.h (renamed from src/systemd/nm-sd-utils-core.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd-utils-dhcp.c (renamed from src/systemd/nm-sd-utils-dhcp.c) | 4 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd-utils-dhcp.h (renamed from src/systemd/nm-sd-utils-dhcp.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd.c (renamed from src/systemd/nm-sd.c) | 4 | ||||
| -rw-r--r-- | src/core/systemd/nm-sd.h (renamed from src/systemd/nm-sd.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/condition.h (renamed from src/systemd/sd-adapt-core/condition.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/conf-parser.h (renamed from src/systemd/sd-adapt-core/conf-parser.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/device-util.h (renamed from src/systemd/sd-adapt-core/device-util.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/khash.h (renamed from src/systemd/sd-adapt-core/khash.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/network-util.h (renamed from src/systemd/sd-adapt-core/sd-daemon.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c (renamed from src/systemd/sd-adapt-core/nm-sd-adapt-core.c) | 4 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h (renamed from src/systemd/sd-adapt-core/nm-sd-adapt-core.h) | 7 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/sd-daemon.h (renamed from src/systemd/sd-adapt-core/sd-device.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/sd-device.h (renamed from src/systemd/sd-adapt-core/udev-util.h) | 0 | ||||
| -rw-r--r-- | src/core/systemd/sd-adapt-core/udev-util.h | 3 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/arp-util.c (renamed from src/systemd/src/libsystemd-network/arp-util.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/arp-util.h (renamed from src/systemd/src/libsystemd-network/arp-util.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-identifier.c (renamed from src/systemd/src/libsystemd-network/dhcp-identifier.c) | 8 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-identifier.h (renamed from src/systemd/src/libsystemd-network/dhcp-identifier.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-internal.h (renamed from src/systemd/src/libsystemd-network/dhcp-internal.h) | 10 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h (renamed from src/systemd/src/libsystemd-network/dhcp-lease-internal.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-network.c (renamed from src/systemd/src/libsystemd-network/dhcp-network.c) | 42 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-option.c (renamed from src/systemd/src/libsystemd-network/dhcp-option.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-packet.c (renamed from src/systemd/src/libsystemd-network/dhcp-packet.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp-protocol.h (renamed from src/systemd/src/libsystemd-network/dhcp-protocol.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp6-internal.h (renamed from src/systemd/src/libsystemd-network/dhcp6-internal.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h (renamed from src/systemd/src/libsystemd-network/dhcp6-lease-internal.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp6-network.c (renamed from src/systemd/src/libsystemd-network/dhcp6-network.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp6-option.c (renamed from src/systemd/src/libsystemd-network/dhcp6-option.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/dhcp6-protocol.h (renamed from src/systemd/src/libsystemd-network/dhcp6-protocol.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/lldp-internal.h (renamed from src/systemd/src/libsystemd-network/lldp-internal.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/lldp-neighbor.c (renamed from src/systemd/src/libsystemd-network/lldp-neighbor.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/lldp-neighbor.h (renamed from src/systemd/src/libsystemd-network/lldp-neighbor.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/lldp-network.c (renamed from src/systemd/src/libsystemd-network/lldp-network.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/lldp-network.h (renamed from src/systemd/src/libsystemd-network/lldp-network.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/network-internal.c | 245 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/network-internal.h | 31 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-dhcp-client.c (renamed from src/systemd/src/libsystemd-network/sd-dhcp-client.c) | 308 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c (renamed from src/systemd/src/libsystemd-network/sd-dhcp-lease.c) | 8 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c (renamed from src/systemd/src/libsystemd-network/sd-dhcp6-client.c) | 29 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c (renamed from src/systemd/src/libsystemd-network/sd-dhcp6-lease.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-ipv4acd.c (renamed from src/systemd/src/libsystemd-network/sd-ipv4acd.c) | 51 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-ipv4ll.c (renamed from src/systemd/src/libsystemd-network/sd-ipv4ll.c) | 27 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd-network/sd-lldp.c (renamed from src/systemd/src/libsystemd-network/sd-lldp.c) | 5 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-event/event-source.h (renamed from src/systemd/src/libsystemd/sd-event/event-source.h) | 14 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-event/event-util.c (renamed from src/systemd/src/libsystemd/sd-event/event-util.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-event/event-util.h (renamed from src/systemd/src/libsystemd/sd-event/event-util.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-event/sd-event.c (renamed from src/systemd/src/libsystemd/sd-event/sd-event.c) | 991 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-id128/id128-util.c (renamed from src/systemd/src/libsystemd/sd-id128/id128-util.c) | 10 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-id128/id128-util.h (renamed from src/systemd/src/libsystemd/sd-id128/id128-util.h) | 6 | ||||
| -rw-r--r-- | src/core/systemd/src/libsystemd/sd-id128/sd-id128.c (renamed from src/systemd/src/libsystemd/sd-id128/sd-id128.c) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/_sd-common.h (renamed from src/systemd/src/systemd/_sd-common.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp-client.h (renamed from src/systemd/src/systemd/sd-dhcp-client.h) | 5 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp-lease.h (renamed from src/systemd/src/systemd/sd-dhcp-lease.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp-option.h (renamed from src/systemd/src/systemd/sd-dhcp-option.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp6-client.h (renamed from src/systemd/src/systemd/sd-dhcp6-client.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp6-lease.h (renamed from src/systemd/src/systemd/sd-dhcp6-lease.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-dhcp6-option.h (renamed from src/systemd/src/systemd/sd-dhcp6-option.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-event.h (renamed from src/systemd/src/systemd/sd-event.h) | 7 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-id128.h (renamed from src/systemd/src/systemd/sd-id128.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-ipv4acd.h (renamed from src/systemd/src/systemd/sd-ipv4acd.h) | 4 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-ipv4ll.h (renamed from src/systemd/src/systemd/sd-ipv4ll.h) | 4 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-lldp.h (renamed from src/systemd/src/systemd/sd-lldp.h) | 2 | ||||
| -rw-r--r-- | src/core/systemd/src/systemd/sd-ndisc.h (renamed from src/systemd/src/systemd/sd-ndisc.h) | 2 | ||||
| -rw-r--r-- | src/core/tests/config/NetworkManager-warn.conf (renamed from src/tests/config/NetworkManager-warn.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/NetworkManager.conf (renamed from src/tests/config/NetworkManager.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/NetworkManager.state (renamed from src/tests/config/NetworkManager.state) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/bad.conf (renamed from src/tests/config/bad.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/conf.d/00-overrides.conf (renamed from src/tests/config/conf.d/00-overrides.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/conf.d/10-more.conf (renamed from src/tests/config/conf.d/10-more.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/conf.d/20-config-enable-1.conf (renamed from src/tests/config/conf.d/20-config-enable-1.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/conf.d/90-last.conf (renamed from src/tests/config/conf.d/90-last.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/global-dns-invalid.conf (renamed from src/tests/config/global-dns-invalid.conf) | 0 | ||||
| -rw-r--r-- | src/core/tests/config/meson.build (renamed from src/tests/config/meson.build) | 4 | ||||
| -rw-r--r-- | src/core/tests/config/nm-test-device.c (renamed from src/tests/config/nm-test-device.c) | 4 | ||||
| -rw-r--r-- | src/core/tests/config/nm-test-device.h (renamed from src/tests/config/nm-test-device.h) | 2 | ||||
| -rw-r--r-- | src/core/tests/config/test-config.c (renamed from src/tests/config/test-config.c) | 8 | ||||
| -rw-r--r-- | src/core/tests/meson.build (renamed from src/tests/meson.build) | 36 | ||||
| -rw-r--r-- | src/core/tests/test-core-with-expect.c (renamed from src/tests/test-core-with-expect.c) | 45 | ||||
| -rw-r--r-- | src/core/tests/test-core.c (renamed from src/tests/test-core.c) | 75 | ||||
| -rw-r--r-- | src/core/tests/test-dcb.c (renamed from src/tests/test-dcb.c) | 4 | ||||
| -rw-r--r-- | src/core/tests/test-ip4-config.c (renamed from src/tests/test-ip4-config.c) | 4 | ||||
| -rw-r--r-- | src/core/tests/test-ip6-config.c (renamed from src/tests/test-ip6-config.c) | 4 | ||||
| -rw-r--r-- | src/core/tests/test-l3cfg.c | 795 | ||||
| -rwxr-xr-x | src/core/tests/test-secret-agent.py (renamed from src/tests/test-secret-agent.py) | 0 | ||||
| -rw-r--r-- | src/core/tests/test-systemd.c (renamed from src/tests/test-systemd.c) | 4 | ||||
| -rw-r--r-- | src/core/tests/test-utils.c (renamed from src/tests/test-utils.c) | 5 | ||||
| -rw-r--r-- | src/core/tests/test-wired-defname.c (renamed from src/tests/test-wired-defname.c) | 4 | ||||
| -rw-r--r-- | src/core/vpn/nm-vpn-connection.c (renamed from src/vpn/nm-vpn-connection.c) | 36 | ||||
| -rw-r--r-- | src/core/vpn/nm-vpn-connection.h (renamed from src/vpn/nm-vpn-connection.h) | 2 | ||||
| -rw-r--r-- | src/core/vpn/nm-vpn-manager.c (renamed from src/vpn/nm-vpn-manager.c) | 4 | ||||
| -rw-r--r-- | src/core/vpn/nm-vpn-manager.h (renamed from src/vpn/nm-vpn-manager.h) | 2 | ||||
| -rw-r--r-- | src/devices/bluetooth/meson.build | 60 | ||||
| -rw-r--r-- | src/devices/ovs/meson.build | 33 | ||||
| -rw-r--r-- | src/dhcp/meson.build | 23 | ||||
| -rw-r--r-- | src/initrd/meson.build | 37 | ||||
| -rw-r--r-- | src/meson.build | 318 | ||||
| -rw-r--r-- | src/ndisc/tests/test-ndisc-fake.c | 538 | ||||
| -rw-r--r-- | src/nm-logging.c | 1036 | ||||
| -rw-r--r-- | src/nm-logging.h | 201 | ||||
| -rw-r--r-- | src/platform/nm-netlink.c | 1518 | ||||
| -rw-r--r-- | src/platform/nm-netlink.h | 616 | ||||
| -rw-r--r-- | src/platform/nm-platform-utils.c | 1785 | ||||
| -rw-r--r-- | src/platform/nm-platform-utils.h | 140 | ||||
| -rw-r--r-- | src/platform/nmp-netns.c | 764 | ||||
| -rw-r--r-- | src/platform/nmp-netns.h | 53 | ||||
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/tests/meson.build | 18 | ||||
| -rw-r--r-- | src/settings/plugins/ifupdown/tests/meson.build | 17 | ||||
| -rw-r--r-- | src/settings/plugins/keyfile/tests/meson.build | 17 | ||||
| -rw-r--r-- | src/systemd/meson.build | 50 | ||||
| -rw-r--r-- | src/systemd/src/libsystemd-network/network-internal.c | 890 | ||||
| -rw-r--r-- | src/systemd/src/libsystemd-network/network-internal.h | 74 | ||||
| -rw-r--r-- | src/tests/test-l3cfg.c | 362 |
972 files changed, 16066 insertions, 16356 deletions
diff --git a/src/NetworkManagerUtils.c b/src/core/NetworkManagerUtils.c index 4739e9dd..54072210 100644 --- a/src/NetworkManagerUtils.c +++ b/src/core/NetworkManagerUtils.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2016 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "NetworkManagerUtils.h" #include <linux/fib_rules.h> #include <linux/pkt_sched.h> +#include <linux/if_ether.h> #include "nm-glib-aux/nm-c-list.h" @@ -152,7 +153,7 @@ nm_utils_get_ip_config_method(NMConnection *connection, int addr_family) s_con = nm_connection_get_setting_connection(connection); - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { g_return_val_if_fail(s_con != NULL, NM_SETTING_IP4_CONFIG_METHOD_AUTO); s_ip = nm_connection_get_setting_ip4_config(connection); @@ -164,19 +165,15 @@ nm_utils_get_ip_config_method(NMConnection *connection, int addr_family) return method; } - if (addr_family == AF_INET6) { - g_return_val_if_fail(s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_return_val_if_fail(s_con != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - s_ip = nm_connection_get_setting_ip6_config(connection); - if (!s_ip) - return NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - - method = nm_setting_ip_config_get_method(s_ip); - g_return_val_if_fail(method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - return method; - } + s_ip = nm_connection_get_setting_ip6_config(connection); + if (!s_ip) + return NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - g_return_val_if_reached("" /* bogus */); + method = nm_setting_ip_config_get_method(s_ip); + g_return_val_if_fail(method != NULL, NM_SETTING_IP6_CONFIG_METHOD_AUTO); + return method; } gboolean @@ -204,7 +201,7 @@ nm_utils_connection_has_default_route(NMConnection *connection, } method = nm_utils_get_ip_config_method(connection, addr_family); - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)) @@ -1312,7 +1309,7 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, else r->table_coerced = nm_platform_route_table_coerce(table ?: (route_table ?: RT_TABLE_MAIN)); - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { guint8 scope; GET_ATTR(NM_IP_ROUTE_ATTRIBUTE_TOS, r4->tos, BYTE, byte, 0); @@ -1338,14 +1335,14 @@ nm_utils_ip_route_attribute_to_platform(int addr_family, if ((variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_SRC)) && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) { if (inet_pton(addr_family, g_variant_get_string(variant, NULL), &addr) == 1) { - if (addr_family == AF_INET) + if (NM_IS_IPv4(addr_family)) r4->pref_src = addr.addr4; else r6->pref_src = addr.addr6; } } - if (addr_family == AF_INET6 + if (!NM_IS_IPv4(addr_family) && (variant = nm_ip_route_get_attribute(s_route, NM_IP_ROUTE_ATTRIBUTE_FROM)) && g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) { int prefix; @@ -1392,7 +1389,7 @@ nm_utils_ip_addresses_to_dbus(int addr_family, GVariant ** out_address_data, GVariant ** out_addresses) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); GVariantBuilder builder_data; GVariantBuilder builder_legacy; char addr_str[NM_UTILS_INET_ADDRSTRLEN]; @@ -1495,15 +1492,12 @@ nm_utils_ip_addresses_to_dbus(int addr_family, g_variant_builder_add( &builder_legacy, "(@ayu@ay)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &address->a6.address, 16, 1), + nm_g_variant_new_ay_in6addr(&address->a6.address), address->a6.plen, - g_variant_new_fixed_array( - G_VARIANT_TYPE_BYTE, + nm_g_variant_new_ay_in6addr( (i == 0 && best_default_route) ? &NMP_OBJECT_CAST_IP6_ROUTE(best_default_route)->gateway - : &in6addr_any, - 16, - 1)); + : &in6addr_any)); } } } @@ -1519,7 +1513,7 @@ nm_utils_ip_routes_to_dbus(int addr_family, GVariant ** out_route_data, GVariant ** out_routes) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDedupMultiIter iter; const NMPObject *obj; GVariantBuilder builder_data; @@ -1622,13 +1616,12 @@ nm_utils_ip_routes_to_dbus(int addr_family, 4, sizeof(guint32))); } else { - g_variant_builder_add( - &builder_legacy, - "(@ayu@ayu)", - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &r->r6.network, 16, 1), - (guint32) r->r6.plen, - g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, &r->r6.gateway, 16, 1), - (guint32) r->r6.metric); + g_variant_builder_add(&builder_legacy, + "(@ayu@ayu)", + nm_g_variant_new_ay_in6addr(&r->r6.network), + (guint32) r->r6.plen, + nm_g_variant_new_ay_in6addr(&r->r6.gateway), + (guint32) r->r6.metric); } } } @@ -1636,3 +1629,203 @@ nm_utils_ip_routes_to_dbus(int addr_family, NM_SET_OUT(out_route_data, g_variant_builder_end(&builder_data)); NM_SET_OUT(out_routes, g_variant_builder_end(&builder_legacy)); } + +/*****************************************************************************/ + +typedef struct { + char *table; + char *rule; +} ShareRule; + +struct _NMUtilsShareRules { + GArray *rules; +}; + +static void +_share_rule_clear(gpointer data) +{ + ShareRule *rule = data; + + g_free(rule->table); + g_free(rule->rule); +} + +NMUtilsShareRules * +nm_utils_share_rules_new(void) +{ + NMUtilsShareRules *self; + + self = g_slice_new(NMUtilsShareRules); + *self = (NMUtilsShareRules){ + .rules = g_array_sized_new(FALSE, FALSE, sizeof(ShareRule), 10), + }; + + g_array_set_clear_func(self->rules, _share_rule_clear); + return self; +} + +void +nm_utils_share_rules_free(NMUtilsShareRules *self) +{ + if (!self) + return; + + g_array_unref(self->rules); + nm_g_slice_free(self); +} + +void +nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take) +{ + ShareRule *rule; + + g_return_if_fail(self); + g_return_if_fail(table); + g_return_if_fail(rule_take); + + rule = nm_g_array_append_new(self->rules, ShareRule); + *rule = (ShareRule){ + .table = g_strdup(table), + .rule = g_steal_pointer(&rule_take), + }; +} + +void +nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared) +{ + guint i; + + g_return_if_fail(self); + + if (self->rules->len == 0) + return; + + /* depending on whether we share or unshare, we add/remote the rules + * in opposite order. */ + if (shared) + i = self->rules->len - 1; + else + i = 0; + + for (;;) { + gs_free_error GError *error = NULL; + ShareRule * rule; + gs_free const char ** argv = NULL; + gs_free char * cmd = NULL; + int status; + + rule = &g_array_index(self->rules, ShareRule, i); + + cmd = g_strdup_printf("%s --table %s %s %s", + IPTABLES_PATH, + rule->table, + shared ? "--insert" : "--delete", + rule->rule); + argv = nm_utils_strsplit_set(cmd, " "); + + nm_log_info(LOGD_SHARING, "Executing: %s", cmd); + if (!g_spawn_sync("/", + (char **) argv, + (char **) NM_PTRARRAY_EMPTY(const char *), + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, + NULL, + NULL, + NULL, + &status, + &error)) { + nm_log_warn(LOGD_SHARING, "Error executing command: %s", error->message); + goto next; + } + if (WEXITSTATUS(status)) { + nm_log_warn(LOGD_SHARING, "** Command returned exit status %d.", WEXITSTATUS(status)); + } + +next: + if (shared) { + if (i == 0) + break; + i--; + } else { + i++; + if (i >= self->rules->len) + break; + } + } +} + +void +nm_utils_share_rules_add_all_rules(NMUtilsShareRules *self, + const char * ip_iface, + in_addr_t addr, + guint plen) +{ + in_addr_t netmask; + in_addr_t network; + char str_mask[NM_UTILS_INET_ADDRSTRLEN]; + char str_addr[NM_UTILS_INET_ADDRSTRLEN]; + + nm_assert(self); + + netmask = _nm_utils_ip4_prefix_to_netmask(plen); + _nm_utils_inet4_ntop(netmask, str_mask); + + network = addr & netmask; + _nm_utils_inet4_ntop(network, str_addr); + + nm_utils_share_rules_add_rule_v( + self, + "nat", + "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", + str_addr, + str_mask, + str_addr, + str_mask); + nm_utils_share_rules_add_rule_v( + self, + "filter", + "FORWARD --destination %s/%s --out-interface %s --match state --state " + "ESTABLISHED,RELATED --jump ACCEPT", + str_addr, + str_mask, + ip_iface); + nm_utils_share_rules_add_rule_v(self, + "filter", + "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", + str_addr, + str_mask, + ip_iface); + nm_utils_share_rules_add_rule_v(self, + "filter", + "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", + ip_iface, + ip_iface); + nm_utils_share_rules_add_rule_v(self, + "filter", + "FORWARD --out-interface %s --jump REJECT", + ip_iface); + nm_utils_share_rules_add_rule_v(self, + "filter", + "FORWARD --in-interface %s --jump REJECT", + ip_iface); + nm_utils_share_rules_add_rule_v( + self, + "filter", + "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", + ip_iface); + nm_utils_share_rules_add_rule_v( + self, + "filter", + "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", + ip_iface); + nm_utils_share_rules_add_rule_v( + self, + "filter", + "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", + ip_iface); + nm_utils_share_rules_add_rule_v( + self, + "filter", + "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", + ip_iface); +} diff --git a/src/NetworkManagerUtils.h b/src/core/NetworkManagerUtils.h index e961c785..2afb5a3e 100644 --- a/src/NetworkManagerUtils.h +++ b/src/core/NetworkManagerUtils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2016 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. @@ -224,4 +224,31 @@ NM_AUTO_DEFINE_FCN(NMDhcpLease *, _nm_auto_unref_dhcplease, nm_dhcp_lease_unref) /*****************************************************************************/ +typedef struct _NMUtilsShareRules NMUtilsShareRules; + +NMUtilsShareRules *nm_utils_share_rules_new(void); + +void nm_utils_share_rules_free(NMUtilsShareRules *self); + +void +nm_utils_share_rules_add_rule_take(NMUtilsShareRules *self, const char *table, char *rule_take); + +static inline void +nm_utils_share_rules_add_rule(NMUtilsShareRules *self, const char *table, const char *rule) +{ + nm_utils_share_rules_add_rule_take(self, table, g_strdup(rule)); +} + +#define nm_utils_share_rules_add_rule_v(self, table, ...) \ + nm_utils_share_rules_add_rule_take((self), (table), g_strdup_printf(__VA_ARGS__)) + +void nm_utils_share_rules_add_all_rules(NMUtilsShareRules *self, + const char * ip_iface, + in_addr_t addr, + guint plen); + +void nm_utils_share_rules_apply(NMUtilsShareRules *self, gboolean shared); + +/*****************************************************************************/ + #endif /* __NETWORKMANAGER_UTILS_H__ */ diff --git a/src/devices/adsl/meson.build b/src/core/devices/adsl/meson.build index 79834d7f..95f61d95 100644 --- a/src/devices/adsl/meson.build +++ b/src/core/devices/adsl/meson.build @@ -1,14 +1,12 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nm-atm-manager.c', - 'nm-device-adsl.c', -) +# SPDX-License-Identifier: LGPL-2.1-or-later libnm_device_plugin_adsl = shared_module( 'nm-device-plugin-adsl', - sources: sources, - dependencies: daemon_nm_default_dep, + sources: files( + 'nm-atm-manager.c', + 'nm-device-adsl.c', + ), + dependencies: core_plugin_dep, c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, @@ -21,5 +19,8 @@ core_plugins += libnm_device_plugin_adsl test( 'check-local-devices-adsl', check_exports, - args: [libnm_device_plugin_adsl.full_path(), linker_script_devices], + args: [ + libnm_device_plugin_adsl.full_path(), + linker_script_devices, + ], ) diff --git a/src/devices/adsl/nm-atm-manager.c b/src/core/devices/adsl/nm-atm-manager.c index 8e9f555d..9be9b5ce 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/core/devices/adsl/nm-atm-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <gmodule.h> #include <libudev.h> @@ -53,7 +53,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES( G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { - return (NMDeviceFactory *) g_object_new(NM_TYPE_ATM_MANAGER, NULL); + return g_object_new(NM_TYPE_ATM_MANAGER, NULL); } /*****************************************************************************/ @@ -239,7 +239,7 @@ nm_atm_manager_init(NMAtmManager *self) { NMAtmManagerPrivate *priv = NM_ATM_MANAGER_GET_PRIVATE(self); - priv->udev_client = nm_udev_client_new((const char *[]){"atm", NULL}, handle_uevent, self); + priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("atm"), handle_uevent, self); } static void @@ -253,7 +253,7 @@ dispose(GObject *object) g_object_weak_unref(G_OBJECT(iter->data), device_destroyed, self); nm_clear_pointer(&priv->devices, g_slist_free); - priv->udev_client = nm_udev_client_unref(priv->udev_client); + priv->udev_client = nm_udev_client_destroy(priv->udev_client); G_OBJECT_CLASS(nm_atm_manager_parent_class)->dispose(object); } diff --git a/src/devices/adsl/nm-device-adsl.c b/src/core/devices/adsl/nm-device-adsl.c index 32615623..34c062a8 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/core/devices/adsl/nm-device-adsl.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Pantelis Koukousoulas <pktoss@gmail.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-adsl.h" @@ -23,8 +23,8 @@ #include "nm-setting-adsl.h" #include "nm-utils.h" +#define _NMLOG_DEVICE_TYPE NMDeviceAdsl #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceAdsl); /*****************************************************************************/ @@ -645,20 +645,20 @@ nm_device_adsl_new(const char *udi, const char *iface, const char *driver, int a g_return_val_if_fail(udi != NULL, NULL); g_return_val_if_fail(atm_index >= 0, NULL); - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_ADSL, - NM_DEVICE_UDI, - udi, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_DRIVER, - driver, - NM_DEVICE_ADSL_ATM_INDEX, - atm_index, - NM_DEVICE_TYPE_DESC, - "ADSL", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_ADSL, - NULL); + return g_object_new(NM_TYPE_DEVICE_ADSL, + NM_DEVICE_UDI, + udi, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_DRIVER, + driver, + NM_DEVICE_ADSL_ATM_INDEX, + atm_index, + NM_DEVICE_TYPE_DESC, + "ADSL", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_ADSL, + NULL); } static void diff --git a/src/devices/adsl/nm-device-adsl.h b/src/core/devices/adsl/nm-device-adsl.h index 95740830..c5c18901 100644 --- a/src/devices/adsl/nm-device-adsl.h +++ b/src/core/devices/adsl/nm-device-adsl.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Author: Pantelis Koukousoulas <pktoss@gmail.com> * Copyright (C) 2009 - 2011 Red Hat Inc. diff --git a/src/core/devices/bluetooth/meson.build b/src/core/devices/bluetooth/meson.build new file mode 100644 index 00000000..d5f26068 --- /dev/null +++ b/src/core/devices/bluetooth/meson.build @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_device_plugin_bluetooth_static = static_library( + 'nm-device-plugin-bluetooth-static', + sources: files( + 'nm-bluez-manager.c', + 'nm-bt-error.c', + 'nm-device-bt.c', + ) + (enable_bluez5_dun ? files('nm-bluez5-dun.c') : files()), + dependencies: [ + core_default_dep, + libnm_wwan_dep, + bluez5_dep, + ], + c_args: daemon_c_flags, +) + +libnm_device_plugin_bluetooth_static_dep = declare_dependency( + link_whole: libnm_device_plugin_bluetooth_static, +) + +libnm_device_plugin_bluetooth = shared_module( + 'nm-device-plugin-bluetooth', + dependencies: [ + core_plugin_dep, + libnm_wwan_dep, + bluez5_dep, + libnm_device_plugin_bluetooth_static_dep, + ], + link_args: ldflags_linker_script_devices, + link_depends: linker_script_devices, + install: true, + install_dir: nm_plugindir, + install_rpath: nm_plugindir, +) + +core_plugins += libnm_device_plugin_bluetooth + +test( + 'check-local-devices-bluetooth', + check_exports, + args: [ + libnm_device_plugin_bluetooth.full_path(), + linker_script_devices + ], +) + +if enable_tests + executable( + 'nm-bt-test', + 'tests/nm-bt-test.c', + dependencies: [ + libNetworkManagerTest_dep, + core_default_dep, + libnm_wwan_dep, + bluez5_dep, + libnm_device_plugin_bluetooth_static_dep, + ], + c_args: test_c_flags, + ) +endif diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/core/devices/bluetooth/nm-bluez-common.h index e70ec3f7..868a985e 100644 --- a/src/devices/bluetooth/nm-bluez-common.h +++ b/src/core/devices/bluetooth/nm-bluez-common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/core/devices/bluetooth/nm-bluez-manager.c index df0bcbbb..dd998d29 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/core/devices/bluetooth/nm-bluez-manager.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-bluez-manager.h" #include <signal.h> #include <stdlib.h> #include <gmodule.h> +#include <linux/if_ether.h> #include "nm-glib-aux/nm-dbus-aux.h" #include "nm-glib-aux/nm-c-list.h" @@ -194,7 +195,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { - return (NMDeviceFactory *) g_object_new(NM_TYPE_BLUEZ_MANAGER, NULL); + return g_object_new(NM_TYPE_BLUEZ_MANAGER, NULL); } /*****************************************************************************/ diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/core/devices/bluetooth/nm-bluez-manager.h index 40a2fcdd..04bfea7d 100644 --- a/src/devices/bluetooth/nm-bluez-manager.h +++ b/src/core/devices/bluetooth/nm-bluez-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2009 - 2019 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/core/devices/bluetooth/nm-bluez5-dun.c index 422c8516..e29884d8 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/core/devices/bluetooth/nm-bluez5-dun.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <sys/socket.h> #include <bluetooth/sdp.h> diff --git a/src/devices/bluetooth/nm-bluez5-dun.h b/src/core/devices/bluetooth/nm-bluez5-dun.h index 94fa5550..020d4119 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.h +++ b/src/core/devices/bluetooth/nm-bluez5-dun.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/core/devices/bluetooth/nm-bt-error.c index 8f5265f8..2e49eb7a 100644 --- a/src/devices/bluetooth/nm-bt-error.c +++ b/src/core/devices/bluetooth/nm-bt-error.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-bt-error.h" diff --git a/src/devices/bluetooth/nm-bt-error.h b/src/core/devices/bluetooth/nm-bt-error.h index 766d2d39..432ae5b4 100644 --- a/src/devices/bluetooth/nm-bt-error.h +++ b/src/core/devices/bluetooth/nm-bt-error.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/core/devices/bluetooth/nm-device-bt.c index c31961df..c07be2d3 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/core/devices/bluetooth/nm-device-bt.c @@ -1,13 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-bt.h" #include <stdio.h> +#include <linux/if_ether.h> #include "nm-core-internal.h" #include "nm-bluez-common.h" @@ -30,8 +31,8 @@ #include "devices/wwan/nm-modem-manager.h" #include "devices/wwan/nm-modem.h" +#define _NMLOG_DEVICE_TYPE NMDeviceBt #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceBt); /*****************************************************************************/ diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/core/devices/bluetooth/nm-device-bt.h index e8a35a21..c2d3bc18 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/core/devices/bluetooth/nm-device-bt.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 Red Hat, Inc. */ diff --git a/src/devices/bluetooth/tests/nm-bt-test.c b/src/core/devices/bluetooth/tests/nm-bt-test.c index a57bb076..0fc8aa87 100644 --- a/src/devices/bluetooth/tests/nm-bt-test.c +++ b/src/core/devices/bluetooth/tests/nm-bt-test.c @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <glib-unix.h> diff --git a/src/devices/meson.build b/src/core/devices/meson.build index 40a5c9dc..66f7aa92 100644 --- a/src/devices/meson.build +++ b/src/core/devices/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later subdir('adsl') diff --git a/src/devices/nm-acd-manager.c b/src/core/devices/nm-acd-manager.c index c9992ff5..b95f90fd 100644 --- a/src/devices/nm-acd-manager.c +++ b/src/core/devices/nm-acd-manager.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#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 "platform/nm-platform.h" #include "nm-utils.h" diff --git a/src/devices/nm-acd-manager.h b/src/core/devices/nm-acd-manager.h index 21001c74..e8ef6f2b 100644 --- a/src/devices/nm-acd-manager.h +++ b/src/core/devices/nm-acd-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ diff --git a/src/devices/nm-device-6lowpan.c b/src/core/devices/nm-device-6lowpan.c index bf63fb73..fe116dd4 100644 --- a/src/devices/nm-device-6lowpan.c +++ b/src/core/devices/nm-device-6lowpan.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-6lowpan.h" @@ -14,8 +14,8 @@ #include "nm-setting-6lowpan.h" #include "nm-utils.h" +#define _NMLOG_DEVICE_TYPE NMDevice6Lowpan #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDevice6Lowpan); /*****************************************************************************/ @@ -285,16 +285,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_6LOWPAN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "6LoWPAN", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_6LOWPAN, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_6LOWPAN, - NULL); + return g_object_new(NM_TYPE_DEVICE_6LOWPAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "6LoWPAN", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_6LOWPAN, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_6LOWPAN, + NULL); } static const char * diff --git a/src/devices/nm-device-6lowpan.h b/src/core/devices/nm-device-6lowpan.h index 60207d76..34ea3c8d 100644 --- a/src/devices/nm-device-6lowpan.h +++ b/src/core/devices/nm-device-6lowpan.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 3ef14a9e..f68c080b 100644 --- a/src/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-bond.h" @@ -17,8 +17,8 @@ #include "nm-core-internal.h" #include "nm-ip4-config.h" +#define _NMLOG_DEVICE_TYPE NMDeviceBond #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceBond); /*****************************************************************************/ @@ -149,6 +149,7 @@ ignore_option(NMSettingBond *s_bond, const char *option, const char *value) static void update_connection(NMDevice *device, NMConnection *connection) { + NMDeviceBond * self = NM_DEVICE_BOND(device); NMSettingBond *s_bond = nm_connection_get_setting_bond(connection); int ifindex = nm_device_get_ifindex(device); NMBondMode mode = NM_BOND_MODE_UNKNOWN; @@ -197,7 +198,10 @@ update_connection(NMDevice *device, NMConnection *connection) } } - nm_setting_bond_add_option(s_bond, option, value); + if (!_nm_setting_bond_validate_option(option, value, NULL)) + _LOGT(LOGD_BOND, "cannot set invalid bond option '%s' = '%s'", option, value); + else + nm_setting_bond_add_option(s_bond, option, value); } } } @@ -264,7 +268,7 @@ set_arp_targets(NMDevice *device, const char *cur_arp_ip_target, const char *new if (cur_len == 0 && new_len == 0) return; - if (_nm_utils_strv_equal((char **) cur_strv, (char **) new_strv)) + if (nm_utils_strv_equal(cur_strv, new_strv)) return; for (i = 0; i < cur_len; i++) @@ -327,6 +331,7 @@ apply_bonding_config(NMDeviceBond *self) NMSettingBond *s_bond; NMBondMode mode; const char * mode_str; + gs_free char * device_bond_mode = NULL; s_bond = nm_device_get_applied_setting(device, NM_TYPE_SETTING_BOND); g_return_val_if_fail(s_bond, FALSE); @@ -338,6 +343,13 @@ apply_bonding_config(NMDeviceBond *self) /* Set mode first, as some other options (e.g. arp_interval) are valid * only for certain modes. */ + device_bond_mode = nm_platform_sysctl_master_get_option(nm_device_get_platform(device), + nm_device_get_ifindex(device), + NM_SETTING_BOND_OPTION_MODE); + /* Need to release all slaves before we can change bond mode */ + if (!nm_streq0(device_bond_mode, mode_str)) + nm_device_master_release_slaves(device); + set_bond_attr_or_default(device, s_bond, NM_SETTING_BOND_OPTION_MODE); set_bond_arp_ip_targets(device, s_bond); @@ -616,18 +628,18 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_BOND, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_DRIVER, - "bonding", - NM_DEVICE_TYPE_DESC, - "Bond", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_BOND, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_BOND, - NULL); + return g_object_new(NM_TYPE_DEVICE_BOND, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_DRIVER, + "bonding", + NM_DEVICE_TYPE_DESC, + "Bond", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_BOND, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_BOND, + NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/devices/nm-device-bond.h b/src/core/devices/nm-device-bond.h index 46be7c23..19301793 100644 --- a/src/devices/nm-device-bond.h +++ b/src/core/devices/nm-device-bond.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/devices/nm-device-bridge.c b/src/core/devices/nm-device-bridge.c index 48dcec1b..c919d85d 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/core/devices/nm-device-bridge.c @@ -1,13 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-bridge.h" #include <stdlib.h> +#include <linux/if_ether.h> #include "NetworkManagerUtils.h" #include "nm-device-private.h" @@ -15,8 +16,8 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceBridge #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceBridge); /*****************************************************************************/ @@ -169,7 +170,7 @@ static void to_sysfs_group_address_sys(const char *group_address, NMEtherAddr *out_addr) { if (group_address == NULL) { - *out_addr = (NMEtherAddr) NM_ETHER_ADDR_INIT(NM_BRIDGE_GROUP_ADDRESS_DEF_BIN); + *out_addr = NM_ETHER_ADDR_INIT(NM_BRIDGE_GROUP_ADDRESS_DEF_BIN); return; } if (!nm_utils_hwaddr_aton(group_address, out_addr, ETH_ALEN)) @@ -1197,18 +1198,18 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_BRIDGE, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_DRIVER, - "bridge", - NM_DEVICE_TYPE_DESC, - "Bridge", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_BRIDGE, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_BRIDGE, - NULL); + return g_object_new(NM_TYPE_DEVICE_BRIDGE, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_DRIVER, + "bridge", + NM_DEVICE_TYPE_DESC, + "Bridge", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_BRIDGE, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_BRIDGE, + NULL); } static gboolean diff --git a/src/devices/nm-device-bridge.h b/src/core/devices/nm-device-bridge.h index c942813e..32437947 100644 --- a/src/devices/nm-device-bridge.h +++ b/src/core/devices/nm-device-bridge.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/devices/nm-device-dummy.c b/src/core/devices/nm-device-dummy.c index 4f6b8cc2..13cfd3b0 100644 --- a/src/devices/nm-device-dummy.c +++ b/src/core/devices/nm-device-dummy.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-dummy.h" @@ -18,8 +18,8 @@ #include "nm-setting-dummy.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceDummy #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceDummy); /*****************************************************************************/ @@ -162,16 +162,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_DUMMY, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Dummy", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_DUMMY, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_DUMMY, - NULL); + return g_object_new(NM_TYPE_DEVICE_DUMMY, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Dummy", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_DUMMY, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_DUMMY, + NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/devices/nm-device-dummy.h b/src/core/devices/nm-device-dummy.h index b3670ef9..2845b4eb 100644 --- a/src/devices/nm-device-dummy.h +++ b/src/core/devices/nm-device-dummy.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/nm-device-ethernet-utils.c b/src/core/devices/nm-device-ethernet-utils.c index 5c35db83..a36d12b7 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/core/devices/nm-device-ethernet-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ethernet-utils.h" diff --git a/src/devices/nm-device-ethernet-utils.h b/src/core/devices/nm-device-ethernet-utils.h index d67b9fa1..133340fc 100644 --- a/src/devices/nm-device-ethernet-utils.h +++ b/src/core/devices/nm-device-ethernet-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ diff --git a/src/devices/nm-device-ethernet.c b/src/core/devices/nm-device-ethernet.c index 2569c426..44428869 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/core/devices/nm-device-ethernet.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2014 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ethernet.h" @@ -12,6 +12,7 @@ #include <stdlib.h> #include <unistd.h> #include <libudev.h> +#include <linux/if_ether.h> #include "nm-device-private.h" #include "nm-act-request.h" @@ -24,7 +25,7 @@ #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-dcb.h" #include "settings/nm-settings-connection.h" #include "nm-config.h" @@ -34,9 +35,10 @@ #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-udev-aux/nm-udev-utils.h" +#include "nm-device-veth.h" +#define _NMLOG_DEVICE_TYPE NMDeviceEthernet #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceEthernet); /*****************************************************************************/ @@ -347,7 +349,9 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * ->check_connection_compatible(device, connection, error)) return FALSE; - if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME)) { + if (nm_connection_is_type(connection, NM_SETTING_PPPOE_SETTING_NAME) + || (nm_connection_is_type(connection, NM_SETTING_VETH_SETTING_NAME) + && NM_IS_DEVICE_VETH(device))) { s_wired = nm_connection_get_setting_wired(connection); } else { s_wired = @@ -891,9 +895,9 @@ link_negotiation_set(NMDevice *device) NMSettingWired * s_wired; gboolean autoneg = TRUE; gboolean link_autoneg; - NMPlatformLinkDuplexType duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; - NMPlatformLinkDuplexType link_duplex; - guint32 speed = 0; + NMPlatformLinkDuplexType duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; + NMPlatformLinkDuplexType link_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; + guint32 speed = 0; guint32 link_speed; s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED); @@ -1360,6 +1364,9 @@ wake_on_lan_enable(NMDevice *device) s_wired = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRED); + if (NM_IS_DEVICE_VETH(device)) + return FALSE; + if (s_wired) { wol = nm_setting_wired_get_wake_on_lan(s_wired); password = nm_setting_wired_get_wake_on_lan_password(s_wired); @@ -1385,7 +1392,7 @@ wake_on_lan_enable(NMDevice *device) found: return nm_platform_ethtool_set_wake_on_lan(nm_device_get_platform(device), nm_device_get_ifindex(device), - wol, + _NM_SETTING_WIRED_WAKE_ON_LAN_CAST(wol), password); } @@ -1493,6 +1500,12 @@ act_stage3_ip_config_start(NMDevice * device, { NMSettingConnection *s_con; const char * connection_type; + int ifindex; + + ifindex = nm_device_get_ifindex(device); + + if (ifindex <= 0) + return NM_ACT_STAGE_RETURN_FAILURE; if (addr_family == AF_INET) { s_con = nm_device_get_applied_setting(device, NM_TYPE_SETTING_CONNECTION); @@ -1525,6 +1538,7 @@ deactivate(NMDevice *device) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE(self); NMSettingDcb * s_dcb; GError * error = NULL; + int ifindex; nm_clear_g_source(&priv->pppoe_wait_id); nm_clear_g_signal_handler(self, &priv->carrier_id); @@ -1553,7 +1567,8 @@ deactivate(NMDevice *device) if (nm_device_get_applied_setting(device, NM_TYPE_SETTING_PPPOE)) priv->last_pppoe_time = nm_utils_get_monotonic_timestamp_sec(); - if (priv->ethtool_prev_set) { + ifindex = nm_device_get_ifindex(device); + if (ifindex > 0 && priv->ethtool_prev_set) { priv->ethtool_prev_set = FALSE; _LOGD(LOGD_DEVICE, @@ -1562,7 +1577,7 @@ deactivate(NMDevice *device) priv->ethtool_prev_speed, nm_platform_link_duplex_type_to_string(priv->ethtool_prev_duplex)); if (!nm_platform_ethtool_set_link_settings(nm_device_get_platform(device), - nm_device_get_ifindex(device), + ifindex, priv->ethtool_prev_autoneg, priv->ethtool_prev_speed, priv->ethtool_prev_duplex)) { @@ -1582,6 +1597,60 @@ complete_connection(NMDevice * device, NMSettingWired *s_wired; NMSettingPppoe *s_pppoe; + if (nm_streq0(nm_connection_get_connection_type(connection), NM_SETTING_VETH_SETTING_NAME)) { + NMSettingVeth *s_veth; + const char * peer_name = NULL; + const char * con_peer_name = NULL; + int ifindex; + + nm_utils_complete_generic(nm_device_get_platform(device), + connection, + NM_SETTING_VETH_SETTING_NAME, + existing_connections, + NULL, + _("Veth connection"), + "veth", + NULL, + TRUE); + + s_veth = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VETH); + if (!s_veth) { + s_veth = (NMSettingVeth *) nm_setting_veth_new(); + nm_connection_add_setting(connection, NM_SETTING(s_veth)); + } + + ifindex = nm_device_get_ip_ifindex(device); + if (ifindex > 0) { + const NMPlatformLink *pllink; + + pllink = nm_platform_link_get(nm_device_get_platform(device), ifindex); + if (pllink && pllink->type == NM_LINK_TYPE_VETH && pllink->parent > 0) { + pllink = nm_platform_link_get(nm_device_get_platform(device), pllink->parent); + + if (pllink && pllink->type == NM_LINK_TYPE_VETH) { + peer_name = pllink->name; + } + } + } + + if (!peer_name) { + nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "cannot find peer for veth device"); + return FALSE; + } + + con_peer_name = nm_setting_veth_get_peer(s_veth); + if (con_peer_name) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "mismatching veth peer \"%s\"", + con_peer_name); + return FALSE; + } else + g_object_set(s_veth, NM_SETTING_VETH_PEER, peer_name, NULL); + + return TRUE; + } + s_pppoe = nm_connection_get_setting_pppoe(connection); /* We can't telepathically figure out the service name or username, so if @@ -1803,7 +1872,7 @@ static void link_changed(NMDevice *device, const NMPlatformLink *pllink) { NM_DEVICE_CLASS(nm_device_ethernet_parent_class)->link_changed(device, pllink); - if (pllink->initialized) + if (!NM_IS_DEVICE_VETH(device) && pllink->initialized) _update_s390_subchannels((NMDeviceEthernet *) device); } @@ -2021,16 +2090,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_ETHERNET, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Ethernet", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_ETHERNET, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_ETHERNET, - NULL); + return g_object_new(NM_TYPE_DEVICE_ETHERNET, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Ethernet", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_ETHERNET, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_ETHERNET, + NULL); } static gboolean diff --git a/src/devices/nm-device-ethernet.h b/src/core/devices/nm-device-ethernet.h index 36b7bc57..6e134d71 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/core/devices/nm-device-ethernet.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/devices/nm-device-factory.c b/src/core/devices/nm-device-factory.c index a238ce1b..81124a8d 100644 --- a/src/devices/nm-device-factory.c +++ b/src/core/devices/nm-device-factory.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-factory.h" @@ -301,7 +301,7 @@ _load_internal_factory(GType factory_gtype, { gs_unref_object NMDeviceFactory *factory = NULL; - factory = (NMDeviceFactory *) g_object_new(factory_gtype, NULL); + factory = g_object_new(factory_gtype, NULL); _add_factory(factory, NULL, callback, user_data); } diff --git a/src/devices/nm-device-factory.h b/src/core/devices/nm-device-factory.h index 5e7a8acd..d9b50563 100644 --- a/src/devices/nm-device-factory.h +++ b/src/core/devices/nm-device-factory.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2014 Red Hat, Inc. */ diff --git a/src/devices/nm-device-generic.c b/src/core/devices/nm-device-generic.c index ccd56366..a319666a 100644 --- a/src/devices/nm-device-generic.c +++ b/src/core/devices/nm-device-generic.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-generic.h" @@ -165,16 +165,16 @@ nm_device_generic_new(const NMPlatformLink *plink, gboolean nm_plugin_missing) { g_return_val_if_fail(plink != NULL, NULL); - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_GENERIC, - NM_DEVICE_IFACE, - plink->name, - NM_DEVICE_TYPE_DESC, - "Generic", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_GENERIC, - NM_DEVICE_NM_PLUGIN_MISSING, - nm_plugin_missing, - NULL); + return g_object_new(NM_TYPE_DEVICE_GENERIC, + NM_DEVICE_IFACE, + plink->name, + NM_DEVICE_TYPE_DESC, + "Generic", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_NM_PLUGIN_MISSING, + nm_plugin_missing, + NULL); } static void diff --git a/src/devices/nm-device-generic.h b/src/core/devices/nm-device-generic.h index 4acc4dc9..48c43523 100644 --- a/src/devices/nm-device-generic.h +++ b/src/core/devices/nm-device-generic.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/devices/nm-device-infiniband.c b/src/core/devices/nm-device-infiniband.c index bae5db64..f54ffcf0 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/core/devices/nm-device-infiniband.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-infiniband.h" @@ -443,19 +443,19 @@ create_device(NMDeviceFactory * factory, && nm_setting_infiniband_get_mac_address(s_infiniband)); } - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_INFINIBAND, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "InfiniBand", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_INFINIBAND, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_INFINIBAND, - /* NOTE: Partition should probably be a different link type! */ - NM_DEVICE_INFINIBAND_IS_PARTITION, - is_partition, - NULL); + return g_object_new(NM_TYPE_DEVICE_INFINIBAND, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "InfiniBand", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_INFINIBAND, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_INFINIBAND, + /* NOTE: Partition should probably be a different link type! */ + NM_DEVICE_INFINIBAND_IS_PARTITION, + is_partition, + NULL); } static const char * diff --git a/src/devices/nm-device-infiniband.h b/src/core/devices/nm-device-infiniband.h index d8be8f21..69994a2d 100644 --- a/src/devices/nm-device-infiniband.h +++ b/src/core/devices/nm-device-infiniband.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ diff --git a/src/devices/nm-device-ip-tunnel.c b/src/core/devices/nm-device-ip-tunnel.c index e01cc7ff..da6afb3b 100644 --- a/src/devices/nm-device-ip-tunnel.c +++ b/src/core/devices/nm-device-ip-tunnel.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ip-tunnel.h" @@ -12,6 +12,7 @@ #include <linux/ip.h> #include <linux/if_tunnel.h> #include <linux/ip6_tunnel.h> +#include <linux/if_ether.h> #include "nm-device-private.h" #include "nm-manager.h" @@ -22,8 +23,8 @@ #include "nm-act-request.h" #include "nm-ip4-config.h" +#define _NMLOG_DEVICE_TYPE NMDeviceIPTunnel #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceIPTunnel); /*****************************************************************************/ @@ -1233,18 +1234,18 @@ create_device(NMDeviceFactory * factory, if (mode == NM_IP_TUNNEL_MODE_UNKNOWN || link_type == NM_LINK_TYPE_UNKNOWN) return NULL; - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_IP_TUNNEL, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "IPTunnel", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_IP_TUNNEL, - NM_DEVICE_LINK_TYPE, - link_type, - NM_DEVICE_IP_TUNNEL_MODE, - mode, - NULL); + return g_object_new(NM_TYPE_DEVICE_IP_TUNNEL, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "IPTunnel", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_IP_TUNNEL, + NM_DEVICE_LINK_TYPE, + link_type, + NM_DEVICE_IP_TUNNEL_MODE, + mode, + NULL); } static const char * diff --git a/src/devices/nm-device-ip-tunnel.h b/src/core/devices/nm-device-ip-tunnel.h index 0d9211ec..0a941cc2 100644 --- a/src/devices/nm-device-ip-tunnel.h +++ b/src/core/devices/nm-device-ip-tunnel.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/devices/nm-device-logging.h b/src/core/devices/nm-device-logging.h index d1291020..844e9949 100644 --- a/src/devices/nm-device-logging.h +++ b/src/core/devices/nm-device-logging.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -8,36 +8,45 @@ #include "nm-device.h" -#define _LOG_DECLARE_SELF(t) \ - _nm_unused static inline NMDevice *_nm_device_log_self_to_device(t *self) \ - { \ - return (NMDevice *) self; \ - } +#if !_NM_CC_SUPPORT_GENERIC + #define _NM_DEVICE_CAST(self) ((NMDevice *) (self)) +#elif !defined(_NMLOG_DEVICE_TYPE) + #define _NM_DEVICE_CAST(self) \ + _Generic((self), NMDevice * \ + : ((NMDevice *) (self)), NMDevice *const \ + : ((NMDevice *) (self))) +#else + #define _NM_DEVICE_CAST(self) \ + _Generic((self), \ + _NMLOG_DEVICE_TYPE * : ((NMDevice *) (self)), \ + _NMLOG_DEVICE_TYPE * const: ((NMDevice *) (self)), \ + NMDevice * : ((NMDevice *) (self)), \ + NMDevice * const: ((NMDevice *) (self))) +#endif #undef _NMLOG_ENABLED #define _NMLOG_ENABLED(level, domain) (nm_logging_enabled((level), (domain))) -#define _NMLOG(level, domain, ...) \ - G_STMT_START \ - { \ - const NMLogLevel _level = (level); \ - const NMLogDomain _domain = (domain); \ - \ - if (nm_logging_enabled(_level, _domain)) { \ - typeof(*self) *const _self = (self); \ - const char *const _ifname = \ - _nm_device_get_iface(_nm_device_log_self_to_device(_self)); \ - \ - nm_log_obj(_level, \ - _domain, \ - _ifname, \ - NULL, \ - _self, \ - "device", \ - "%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - NM_PRINT_FMT_QUOTED(_ifname, "(", _ifname, ")", "[null]") \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ +#define _NMLOG(level, domain, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ + if (nm_logging_enabled(_level, _domain)) { \ + typeof(*self) *const _self = (self); \ + const char *const _ifname = _nm_device_get_iface(_NM_DEVICE_CAST(_self)); \ + \ + nm_log_obj(_level, \ + _domain, \ + _ifname, \ + NULL, \ + _self, \ + "device", \ + "%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_PRINT_FMT_QUOTED(_ifname, "(", _ifname, ")", "[null]") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ G_STMT_END #endif /* __NETWORKMANAGER_DEVICE_LOGGING_H__ */ diff --git a/src/devices/nm-device-macsec.c b/src/core/devices/nm-device-macsec.c index 7d738b42..51b820a1 100644 --- a/src/devices/nm-device-macsec.c +++ b/src/core/devices/nm-device-macsec.c @@ -1,12 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-macsec.h" +#include <linux/if_ether.h> + #include "nm-act-request.h" #include "nm-device-private.h" #include "platform/nm-platform.h" @@ -18,8 +20,8 @@ #include "supplicant/nm-supplicant-interface.h" #include "supplicant/nm-supplicant-config.h" +#define _NMLOG_DEVICE_TYPE NMDeviceMacsec #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceMacsec); /*****************************************************************************/ @@ -1023,16 +1025,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_MACSEC, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Macsec", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_MACSEC, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_MACSEC, - NULL); + return g_object_new(NM_TYPE_DEVICE_MACSEC, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Macsec", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_MACSEC, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_MACSEC, + NULL); } static const char * diff --git a/src/devices/nm-device-macsec.h b/src/core/devices/nm-device-macsec.h index 9a2f230b..e91fe51c 100644 --- a/src/devices/nm-device-macsec.h +++ b/src/core/devices/nm-device-macsec.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/nm-device-macvlan.c b/src/core/devices/nm-device-macvlan.c index d9e71c8c..e8b39ed6 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/core/devices/nm-device-macvlan.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-macvlan.h" @@ -21,8 +21,8 @@ #include "nm-ip4-config.h" #include "nm-utils.h" +#define _NMLOG_DEVICE_TYPE NMDeviceMacvlan #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceMacvlan); /*****************************************************************************/ @@ -598,18 +598,18 @@ create_device(NMDeviceFactory * factory, link_type = tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_MACVLAN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Macvlan", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_MACVLAN, - NM_DEVICE_LINK_TYPE, - link_type, - NM_DEVICE_MACVLAN_TAP, - tap, - NULL); + return g_object_new(NM_TYPE_DEVICE_MACVLAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Macvlan", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_MACVLAN, + NM_DEVICE_LINK_TYPE, + link_type, + NM_DEVICE_MACVLAN_TAP, + tap, + NULL); } static const char * diff --git a/src/devices/nm-device-macvlan.h b/src/core/devices/nm-device-macvlan.h index f36a7a4a..109a2bcd 100644 --- a/src/devices/nm-device-macvlan.h +++ b/src/core/devices/nm-device-macvlan.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/devices/nm-device-ppp.c b/src/core/devices/nm-device-ppp.c index 82861bda..4040f2d3 100644 --- a/src/devices/nm-device-ppp.c +++ b/src/core/devices/nm-device-ppp.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ppp.h" @@ -18,8 +18,8 @@ #include "ppp/nm-ppp-manager-call.h" #include "ppp/nm-ppp-status.h" +#define _NMLOG_DEVICE_TYPE NMDevicePpp #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDevicePpp); /*****************************************************************************/ @@ -316,16 +316,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_PPP, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Ppp", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_PPP, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_PPP, - NULL); + return g_object_new(NM_TYPE_DEVICE_PPP, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Ppp", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_PPP, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_PPP, + NULL); } static gboolean diff --git a/src/devices/nm-device-ppp.h b/src/core/devices/nm-device-ppp.h index 99132a3e..24c119ab 100644 --- a/src/devices/nm-device-ppp.h +++ b/src/core/devices/nm-device-ppp.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/nm-device-private.h b/src/core/devices/nm-device-private.h index 5f8eff18..8675a699 100644 --- a/src/devices/nm-device-private.h +++ b/src/core/devices/nm-device-private.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2011 Red Hat, Inc. @@ -54,9 +54,7 @@ gboolean nm_device_set_ip_iface(NMDevice *self, const char *iface); void nm_device_activate_schedule_stage3_ip_config_start(NMDevice *device); -gboolean nm_device_activate_stage3_ip4_start(NMDevice *self); - -gboolean nm_device_activate_stage3_ip6_start(NMDevice *self); +gboolean nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family); gboolean nm_device_bring_up(NMDevice *self, gboolean wait, gboolean *no_firmware); @@ -129,6 +127,8 @@ void nm_device_recheck_available_connections(NMDevice *device); void nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLogDomain log_domain); +void nm_device_master_release_slaves(NMDevice *self); + void nm_device_set_carrier(NMDevice *self, gboolean carrier); void nm_device_queue_recheck_assume(NMDevice *device); diff --git a/src/devices/nm-device-tun.c b/src/core/devices/nm-device-tun.c index 94805255..edca69e9 100644 --- a/src/devices/nm-device-tun.c +++ b/src/core/devices/nm-device-tun.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-tun.h" @@ -19,8 +19,8 @@ #include "nm-setting-tun.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceTun #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceTun); /*****************************************************************************/ @@ -550,16 +550,16 @@ create_device(NMDeviceFactory * factory, NM_SETTING_TUN_SETTING_NAME), NULL); - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_TUN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Tun", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_TUN, - NM_DEVICE_LINK_TYPE, - (guint) NM_LINK_TYPE_TUN, - NULL); + return g_object_new(NM_TYPE_DEVICE_TUN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Tun", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_TUN, + NM_DEVICE_LINK_TYPE, + (guint) NM_LINK_TYPE_TUN, + NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/devices/nm-device-tun.h b/src/core/devices/nm-device-tun.h index 32d515c1..84497ea0 100644 --- a/src/devices/nm-device-tun.h +++ b/src/core/devices/nm-device-tun.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/devices/nm-device-veth.c b/src/core/devices/nm-device-veth.c index f61bc99f..e0ba843d 100644 --- a/src/devices/nm-device-veth.c +++ b/src/core/devices/nm-device-veth.c @@ -1,20 +1,22 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdlib.h> +#include "nm-core-internal.h" #include "nm-device-veth.h" #include "nm-device-private.h" #include "nm-manager.h" #include "platform/nm-platform.h" #include "nm-device-factory.h" +#include "nm-setting-veth.h" +#define _NMLOG_DEVICE_TYPE NMDeviceVeth #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceVeth); /*****************************************************************************/ @@ -42,9 +44,10 @@ update_properties(NMDevice *device) ifindex = nm_device_get_ifindex(device); - if (!nm_platform_link_veth_get_properties(nm_device_get_platform(device), - ifindex, - &peer_ifindex)) + if (ifindex <= 0 + || !nm_platform_link_veth_get_properties(nm_device_get_platform(device), + ifindex, + &peer_ifindex)) peer_ifindex = 0; nm_device_parent_set_ifindex(device, peer_ifindex); @@ -71,6 +74,53 @@ link_changed(NMDevice *device, const NMPlatformLink *pllink) update_properties(device); } +static gboolean +create_and_realize(NMDevice * device, + NMConnection * connection, + NMDevice * parent, + const NMPlatformLink **out_plink, + GError ** error) +{ + const char * iface = nm_device_get_iface(device); + NMSettingVeth *s_veth; + int r; + + s_veth = _nm_connection_get_setting(connection, NM_TYPE_SETTING_VETH); + if (!s_veth) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_CREATION_FAILED, + "Profile %s (%s) is not a suitable veth profile", + nm_connection_get_id(connection), + nm_connection_get_uuid(connection)); + return FALSE; + } + + r = nm_platform_link_veth_add(nm_device_get_platform(device), + iface, + nm_setting_veth_get_peer(s_veth), + out_plink); + if (r < 0) { + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create veth interface '%s' for '%s': %s", + iface, + nm_connection_get_id(connection), + nm_strerror(r)); + return FALSE; + } + return TRUE; +} + +/*****************************************************************************/ + +static NMDeviceCapabilities +get_generic_capabilities(NMDevice *device) +{ + return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; +} + /*****************************************************************************/ static void @@ -136,6 +186,8 @@ nm_device_veth_class_init(NMDeviceVethClass *klass) device_class->can_unmanaged_external_down = can_unmanaged_external_down; device_class->link_changed = link_changed; device_class->parent_changed_notify = parent_changed_notify; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; obj_properties[PROP_PEER] = g_param_spec_string(NM_DEVICE_VETH_PEER, "", @@ -159,20 +211,22 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_VETH, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Veth", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_VETH, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_VETH, - NULL); + return g_object_new(NM_TYPE_DEVICE_VETH, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Veth", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_VETH, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_VETH, + NULL); } -NM_DEVICE_FACTORY_DEFINE_INTERNAL(VETH, - Veth, - veth, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_VETH), - factory_class->create_device = create_device;); +NM_DEVICE_FACTORY_DEFINE_INTERNAL( + VETH, + Veth, + veth, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES(NM_LINK_TYPE_VETH) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES(NM_SETTING_VETH_SETTING_NAME), + factory_class->create_device = create_device;); diff --git a/src/devices/nm-device-veth.h b/src/core/devices/nm-device-veth.h index e3867446..d43a0a4b 100644 --- a/src/devices/nm-device-veth.h +++ b/src/core/devices/nm-device-veth.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/devices/nm-device-vlan.c b/src/core/devices/nm-device-vlan.c index bb6fdc05..bfde60ef 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/core/devices/nm-device-vlan.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2012 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-vlan.h" @@ -22,8 +22,8 @@ #include "nm-core-internal.h" #include "platform/nmp-object.h" +#define _NMLOG_DEVICE_TYPE NMDeviceVlan #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceVlan); /*****************************************************************************/ @@ -117,7 +117,7 @@ parent_hwaddr_maybe_changed(NMDevice *parent, GParamSpec *pspec, gpointer user_d */ s_ip6 = nm_connection_get_setting_ip6_config(connection); if (s_ip6) - nm_device_reactivate_ip6_config(device, s_ip6, s_ip6); + nm_device_reactivate_ip_config(device, AF_INET6, s_ip6, s_ip6); } } @@ -614,18 +614,18 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_VLAN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_DRIVER, - "8021q", - NM_DEVICE_TYPE_DESC, - "VLAN", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_VLAN, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_VLAN, - NULL); + return g_object_new(NM_TYPE_DEVICE_VLAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_DRIVER, + "8021q", + NM_DEVICE_TYPE_DESC, + "VLAN", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_VLAN, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_VLAN, + NULL); } static const char * diff --git a/src/devices/nm-device-vlan.h b/src/core/devices/nm-device-vlan.h index 5bf11cd9..5270706f 100644 --- a/src/devices/nm-device-vlan.h +++ b/src/core/devices/nm-device-vlan.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/devices/nm-device-vrf.c b/src/core/devices/nm-device-vrf.c index ae0ecc60..4fec59ba 100644 --- a/src/devices/nm-device-vrf.c +++ b/src/core/devices/nm-device-vrf.c @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-vrf.h" @@ -12,8 +12,8 @@ #include "platform/nm-platform.h" #include "settings/nm-settings.h" +#define _NMLOG_DEVICE_TYPE NMDeviceVrf #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceVrf); /*****************************************************************************/ diff --git a/src/devices/nm-device-vrf.h b/src/core/devices/nm-device-vrf.h index eb09bd95..5169041c 100644 --- a/src/devices/nm-device-vrf.h +++ b/src/core/devices/nm-device-vrf.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef __NETWORKMANAGER_DEVICE_VRF_H__ #define __NETWORKMANAGER_DEVICE_VRF_H__ diff --git a/src/devices/nm-device-vxlan.c b/src/core/devices/nm-device-vxlan.c index 083f29c6..f16a52c4 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/core/devices/nm-device-vxlan.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-vxlan.h" @@ -19,8 +19,8 @@ #include "nm-ip4-config.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceVxlan #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceVxlan); /*****************************************************************************/ @@ -162,11 +162,10 @@ create_and_realize(NMDevice * device, NMPlatformLnkVxlan props = {}; NMSettingVxlan * s_vxlan; const char * str; - int ret; int r; s_vxlan = nm_connection_get_setting_vxlan(connection); - g_assert(s_vxlan); + g_return_val_if_fail(s_vxlan, FALSE); if (parent) props.parent_ifindex = nm_device_get_ifindex(parent); @@ -175,19 +174,17 @@ create_and_realize(NMDevice * device, str = nm_setting_vxlan_get_local(s_vxlan); if (str) { - ret = inet_pton(AF_INET, str, &props.local); - if (ret != 1) - ret = inet_pton(AF_INET6, str, &props.local6); - if (ret != 1) + if (!nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &props.local) + && !nm_utils_parse_inaddr_bin(AF_INET6, str, NULL, &props.local6)) return FALSE; } str = nm_setting_vxlan_get_remote(s_vxlan); - ret = inet_pton(AF_INET, str, &props.group); - if (ret != 1) - ret = inet_pton(AF_INET6, str, &props.group6); - if (ret != 1) - return FALSE; + if (str) { + if (!nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &props.group) + && !nm_utils_parse_inaddr_bin(AF_INET6, str, NULL, &props.group6)) + return FALSE; + } props.tos = nm_setting_vxlan_get_tos(s_vxlan); props.ttl = nm_setting_vxlan_get_ttl(s_vxlan); @@ -218,21 +215,26 @@ create_and_realize(NMDevice * device, } static gboolean -address_matches(const char *str, in_addr_t addr4, struct in6_addr *addr6) +address_matches(const char *candidate, in_addr_t addr4, struct in6_addr *addr6) { - in_addr_t new_addr4 = 0; - struct in6_addr new_addr6 = {}; + NMIPAddr candidate_addr; + int addr_family; - if (!str) { - return addr4 == 0 && !memcmp(addr6, &in6addr_any, sizeof(in6addr_any)); - } + if (!candidate) + return addr4 == 0u && IN6_IS_ADDR_UNSPECIFIED(addr6); - if (inet_pton(AF_INET, str, &new_addr4) == 1) - return new_addr4 == addr4; - else if (inet_pton(AF_INET6, str, &new_addr6) == 1) - return !memcmp(&new_addr6, addr6, sizeof(new_addr6)); - else + if (!nm_utils_parse_inaddr_bin(AF_UNSPEC, candidate, &addr_family, &candidate_addr)) + return FALSE; + + if (!nm_ip_addr_equal(addr_family, + &candidate_addr, + NM_IS_IPv4(addr_family) ? (gpointer) &addr4 : addr6)) return FALSE; + + if (NM_IS_IPv4(addr_family)) + return IN6_IS_ADDR_UNSPECIFIED(addr6); + else + return addr4 == 0u; } static gboolean @@ -757,16 +759,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_VXLAN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "Vxlan", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_VXLAN, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_VXLAN, - NULL); + return g_object_new(NM_TYPE_DEVICE_VXLAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "Vxlan", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_VXLAN, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_VXLAN, + NULL); } static const char * diff --git a/src/devices/nm-device-vxlan.h b/src/core/devices/nm-device-vxlan.h index 89683b02..4c4165e5 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/core/devices/nm-device-vxlan.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013, 2014 Red Hat, Inc. */ diff --git a/src/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index 9bd23e65..fd057ded 100644 --- a/src/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Javier Arteaga <jarteaga@jbeta.is> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-wireguard.h" @@ -22,8 +22,8 @@ #include "nm-act-request.h" #include "dns/nm-dns-manager.h" +#define _NMLOG_DEVICE_TYPE NMDeviceWireGuard #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceWireGuard); /*****************************************************************************/ @@ -118,6 +118,9 @@ typedef struct { CList lst_peers_head; GHashTable *peers; + /* counts the numbers of peers that are currently resolving. */ + guint peers_resolving_cnt; + gint64 resolve_next_try_at; gint64 link_config_last_at; @@ -506,9 +509,52 @@ _peers_find(NMDeviceWireGuardPrivate *priv, NMWireGuardPeer *peer) return g_hash_table_lookup(priv->peers, &peer); } +static guint +_peers_resolving_cnt(NMDeviceWireGuardPrivate *priv) +{ + nm_assert(priv); +#if NM_MORE_ASSERTS > 3 + { + PeerData *peer_data; + guint cnt = 0; + + c_list_for_each_entry (peer_data, &priv->lst_peers_head, lst_peers) { + if (peer_data->ep_resolv.cancellable) + cnt++; + } + nm_assert(cnt == priv->peers_resolving_cnt); + } +#endif + + return priv->peers_resolving_cnt; +} + +static void +_peers_resolving_cnt_decrement(NMDeviceWireGuard *self) +{ + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + + nm_assert(priv); + nm_assert(priv->peers_resolving_cnt > 0); + + priv->peers_resolving_cnt--; + + nm_assert(_peers_resolving_cnt(priv) == priv->peers_resolving_cnt); + + if (priv->peers_resolving_cnt == 0) { + if (nm_device_get_state(NM_DEVICE(self)) == NM_DEVICE_STATE_CONFIG) { + _LOGT(LOGD_DEVICE, + "activation delayed to resolve DNS names of peers: completed, proceed now"); + nm_device_activate_schedule_stage2_device_config(NM_DEVICE(self), FALSE); + } + } +} + static void -_peers_remove(NMDeviceWireGuardPrivate *priv, PeerData *peer_data) +_peers_remove(NMDeviceWireGuard *self, PeerData *peer_data) { + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + nm_assert(peer_data); nm_assert(g_hash_table_lookup(priv->peers, peer_data) == peer_data); @@ -517,13 +563,16 @@ _peers_remove(NMDeviceWireGuardPrivate *priv, PeerData *peer_data) c_list_unlink_stale(&peer_data->lst_peers); nm_wireguard_peer_unref(peer_data->peer); - nm_clear_g_cancellable(&peer_data->ep_resolv.cancellable); + if (nm_clear_g_cancellable(&peer_data->ep_resolv.cancellable)) + _peers_resolving_cnt_decrement(self); g_slice_free(PeerData, peer_data); if (c_list_is_empty(&priv->lst_peers_head)) { nm_clear_g_source(&priv->resolve_next_try_id); nm_clear_g_source(&priv->link_config_delayed_id); } + + nm_assert(_peers_resolving_cnt(priv) == priv->peers_resolving_cnt); } static PeerData * @@ -675,8 +724,9 @@ _peers_retry_in_msec(PeerData *peer_data, gboolean after_failure) static void _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) { - NMDeviceWireGuard *self; - PeerData * peer_data; + NMDeviceWireGuard * self; + NMDeviceWireGuardPrivate *priv; + PeerData * peer_data; gs_free_error GError *resolv_error = NULL; GList * list; gboolean changed = FALSE; @@ -692,10 +742,13 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) peer_data = user_data; self = peer_data->self; + priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - g_clear_object(&peer_data->ep_resolv.cancellable); + if (nm_clear_g_object(&peer_data->ep_resolv.cancellable)) + _peers_resolving_cnt_decrement(self); nm_assert((!resolv_error) != (!list)); + nm_assert(_peers_resolving_cnt(priv) == priv->peers_resolving_cnt); #define _retry_in_msec_to_string(retry_in_msec, s_retry) \ ({ \ @@ -797,8 +850,6 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) _peers_resolve_retry_reschedule_for_peer(self, peer_data, retry_in_msec); if (changed) { - NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - /* schedule the job in the background, to give multiple resolve events time * to complete. */ nm_clear_g_source(&priv->link_config_delayed_id); @@ -812,6 +863,7 @@ _peers_resolve_cb(GObject *source_object, GAsyncResult *res, gpointer user_data) static void _peers_resolve_start(NMDeviceWireGuard *self, PeerData *peer_data) { + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); gs_unref_object GResolver *resolver = NULL; const char * host; @@ -820,6 +872,7 @@ _peers_resolve_start(NMDeviceWireGuard *self, PeerData *peer_data) nm_assert(!peer_data->ep_resolv.cancellable); peer_data->ep_resolv.cancellable = g_cancellable_new(); + priv->peers_resolving_cnt++; /* set a special next-try timestamp. It is positive, and indicates * that we are in the process of trying. @@ -841,6 +894,8 @@ _peers_resolve_start(NMDeviceWireGuard *self, PeerData *peer_data) nm_wireguard_peer_get_public_key(peer_data->peer), host, nm_wireguard_peer_get_endpoint(peer_data->peer)); + + nm_assert(_peers_resolving_cnt(priv) == priv->peers_resolving_cnt); } static void @@ -915,7 +970,8 @@ _peers_update(NMDeviceWireGuard *self, if (nm_sock_addr_union_cmp(&peer_data->ep_resolv.sockaddr, &sockaddr) != 0) changed = TRUE; - nm_clear_g_cancellable(&peer_data->ep_resolv.cancellable); + if (nm_clear_g_cancellable(&peer_data->ep_resolv.cancellable)) + _peers_resolving_cnt_decrement(self); peer_data->ep_resolv = (PeerEndpointResolveData){ .sockaddr = sockaddr, @@ -948,12 +1004,13 @@ _peers_update(NMDeviceWireGuard *self, } static void -_peers_remove_all(NMDeviceWireGuardPrivate *priv) +_peers_remove_all(NMDeviceWireGuard *self) { - PeerData *peer_data; + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + PeerData * peer_data; while ((peer_data = c_list_first_entry(&priv->lst_peers_head, PeerData, lst_peers))) - _peers_remove(priv, peer_data); + _peers_remove(self, peer_data); } static void @@ -984,7 +1041,7 @@ _peers_update_all(NMDeviceWireGuard *self, NMSettingWireGuard *s_wg, gboolean *o c_list_for_each_entry_safe (peer_data, peer_data_safe, &priv->lst_peers_head, lst_peers) { if (peer_data->dirty_update_all) { - _peers_remove(priv, peer_data); + _peers_remove(self, peer_data); peers_removed = TRUE; } } @@ -1515,9 +1572,11 @@ link_config_delayed_resolver_cb(gpointer user_data) static NMActStageReturn act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) { - NMDeviceSysIfaceState sys_iface_state; - NMDeviceStateReason failure_reason; - NMActStageReturn ret; + NMDeviceWireGuard * self = NM_DEVICE_WIREGUARD(device); + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + NMDeviceSysIfaceState sys_iface_state; + NMDeviceStateReason failure_reason; + NMActStageReturn ret; sys_iface_state = nm_device_sys_iface_state_get(device); @@ -1533,17 +1592,25 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) : LINK_CONFIG_MODE_FULL, &failure_reason); - if (sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_ASSUME) { - /* this never fails. */ - return NM_ACT_STAGE_RETURN_SUCCESS; - } - if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + if (sys_iface_state == NM_DEVICE_SYS_IFACE_STATE_ASSUME) { + /* this never fails. */ + return NM_ACT_STAGE_RETURN_SUCCESS; + } + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, failure_reason); NM_SET_OUT(out_failure_reason, failure_reason); return NM_ACT_STAGE_RETURN_FAILURE; } + nm_assert(NM_IN_SET(ret, NM_ACT_STAGE_RETURN_SUCCESS, NM_ACT_STAGE_RETURN_POSTPONE)); + + if (ret == NM_ACT_STAGE_RETURN_SUCCESS && _peers_resolving_cnt(priv) > 0u) { + _LOGT(LOGD_DEVICE, + "activation delayed to resolve DNS names of peers: resolving and waiting..."); + return NM_ACT_STAGE_RETURN_POSTPONE; + } + return ret; } @@ -1732,7 +1799,7 @@ _device_cleanup(NMDeviceWireGuard *self) { NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); - _peers_remove_all(priv); + _peers_remove_all(self); _secrets_cancel(self); @@ -2005,16 +2072,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_WIREGUARD, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "WireGuard", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_WIREGUARD, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_WIREGUARD, - NULL); + return g_object_new(NM_TYPE_DEVICE_WIREGUARD, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "WireGuard", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_WIREGUARD, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_WIREGUARD, + NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/devices/nm-device-wireguard.h b/src/core/devices/nm-device-wireguard.h index f562f356..7e18bdba 100644 --- a/src/devices/nm-device-wireguard.h +++ b/src/core/devices/nm-device-wireguard.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Javier Arteaga <jarteaga@jbeta.is> */ diff --git a/src/devices/nm-device-wpan.c b/src/core/devices/nm-device-wpan.c index 195603dc..2f3b16ff 100644 --- a/src/devices/nm-device-wpan.c +++ b/src/core/devices/nm-device-wpan.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-manager.h" #include "nm-device-wpan.h" @@ -20,8 +20,8 @@ #include "nm-setting-wpan.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceWpan #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceWpan); /*****************************************************************************/ @@ -236,16 +236,16 @@ create_device(NMDeviceFactory * factory, NMConnection * connection, gboolean * out_ignore) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_WPAN, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "WPAN", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_WPAN, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_WPAN, - NULL); + return g_object_new(NM_TYPE_DEVICE_WPAN, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "WPAN", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_WPAN, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_WPAN, + NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL( diff --git a/src/devices/nm-device-wpan.h b/src/core/devices/nm-device-wpan.h index 4bc4f243..969929ae 100644 --- a/src/devices/nm-device-wpan.h +++ b/src/core/devices/nm-device-wpan.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk> */ diff --git a/src/devices/nm-device.c b/src/core/devices/nm-device.c index 0be05f23..040dd0b4 100644 --- a/src/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -1,14 +1,13 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device.h" -#include <netinet/in.h> #include <unistd.h> #include <sys/ioctl.h> #include <signal.h> @@ -16,16 +15,20 @@ #include <sys/wait.h> #include <arpa/inet.h> #include <fcntl.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <linux/if.h> #include <linux/if_addr.h> -#include <linux/if_arp.h> #include <linux/rtnetlink.h> +#include <linux/if_ether.h> +#include <linux/if_infiniband.h> #include "nm-std-aux/unaligned.h" #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-glib-aux/nm-random-utils.h" #include "systemd/nm-sd-utils-shared.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" +#include "nm-base/nm-ethtool-base.h" #include "nm-libnm-core-intern/nm-common-macros.h" #include "nm-device-private.h" #include "nm-l3cfg.h" @@ -33,7 +36,7 @@ #include "NetworkManagerUtils.h" #include "nm-manager.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "platform/nmp-object.h" #include "platform/nmp-rules-manager.h" #include "ndisc/nm-ndisc.h" @@ -52,6 +55,7 @@ #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "nm-setting-ethtool.h" +#include "nm-setting-ovs-external-ids.h" #include "nm-setting-user.h" #include "nm-auth-utils.h" #include "nm-keep-alive.h" @@ -74,7 +78,6 @@ #include "nm-device-wireguard.h" #include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDevice); /*****************************************************************************/ @@ -131,7 +134,7 @@ typedef struct { NMPlatformAsyncCallback callback; gpointer callback_data; guint num_vfs; - NMTernary autoprobe; + NMOptionBool autoprobe; } SriovOp; typedef void (*AcdCallback)(NMDevice *, NMIP4Config **, gboolean); @@ -202,11 +205,28 @@ struct _NMDeviceConnectivityHandle { typedef struct { int ifindex; NMEthtoolFeatureStates *features; - NMTernary requested[_NM_ETHTOOL_ID_FEATURE_NUM]; + NMOptionBool requested[_NM_ETHTOOL_ID_FEATURE_NUM]; NMEthtoolCoalesceState *coalesce; NMEthtoolRingState * ring; } EthtoolState; +typedef enum { + RESOLVER_WAIT_ADDRESS = 0, + RESOLVER_IN_PROGRESS, + RESOLVER_DONE, +} ResolverState; + +typedef struct { + ResolverState state; + GResolver * resolver; + GInetAddress *address; + GCancellable *cancellable; + char * hostname; + NMDevice * device; + guint timeout_id; /* Used when waiting for the address */ + int addr_family; +} HostnameResolver; + /*****************************************************************************/ enum { @@ -219,6 +239,7 @@ enum { REMOVED, RECHECK_AUTO_ACTIVATE, RECHECK_ASSUME, + DNS_LOOKUP_DONE, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = {0}; @@ -326,6 +347,14 @@ typedef struct _NMDevicePrivate { int auth_retries; union { + struct { + HostnameResolver *hostname_resolver_6; + HostnameResolver *hostname_resolver_4; + }; + HostnameResolver *hostname_resolver_x[2]; + }; + + union { const guint8 hw_addr_len; /* read-only */ guint8 hw_addr_len_; }; @@ -357,6 +386,8 @@ typedef struct _NMDevicePrivate { bool assume_state_guess_assume : 1; char *assume_state_connection_uuid; + guint64 udi_id; + GHashTable *available_connections; char * hw_addr; char * hw_addr_perm; @@ -411,6 +442,7 @@ typedef struct _NMDevicePrivate { guint carrier_defer_id; guint carrier_wait_id; gulong config_changed_id; + gulong ifindex_changed_id; guint32 mtu; guint32 ip6_mtu; guint32 mtu_initial; @@ -611,6 +643,7 @@ typedef struct _NMDevicePrivate { /* master interface for bridge/bond/team slave */ NMDevice *master; gulong master_ready_id; + int master_ifindex; /* slave management */ CList slaves; /* list of SlaveInfo */ @@ -695,6 +728,8 @@ 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 void _carrier_wait_check_queued_act_request(NMDevice *self); static gint64 _get_carrier_wait_ms(NMDevice *self); @@ -726,23 +761,10 @@ static void concheck_update_state(NMDevice * self, NMConnectivityState state, gboolean is_periodic); -static void activate_stage4_ip_config_timeout_4(NMDevice *self); -static void activate_stage4_ip_config_timeout_6(NMDevice *self); - -static void (*const activate_stage4_ip_config_timeout_x[2])(NMDevice *self) = { - activate_stage4_ip_config_timeout_6, - activate_stage4_ip_config_timeout_4, -}; - static void sriov_op_cb(GError *error, gpointer user_data); -static void activate_stage5_ip_config_result_4(NMDevice *self); -static void activate_stage5_ip_config_result_6(NMDevice *self); - -static void (*const activate_stage5_ip_config_result_x[2])(NMDevice *self) = { - activate_stage5_ip_config_result_6, - activate_stage5_ip_config_result_4, -}; +static void device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self); +static gboolean device_link_changed(NMDevice *self); /*****************************************************************************/ @@ -879,6 +901,22 @@ static NM_UTILS_LOOKUP_STR_DEFINE(mtu_source_to_str, /*****************************************************************************/ +static void +_hostname_resolver_free(HostnameResolver *resolver) +{ + if (!resolver) + return; + + nm_clear_g_source(&resolver->timeout_id); + nm_clear_g_cancellable(&resolver->cancellable); + nm_g_object_unref(resolver->resolver); + nm_g_object_unref(resolver->address); + g_free(resolver->hostname); + nm_g_slice_free(resolver); +} + +/*****************************************************************************/ + static NMSettingIP6ConfigPrivacy _ip6_privacy_clamp(NMSettingIP6ConfigPrivacy use_tempaddr) { @@ -1294,7 +1332,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) /* the route table setting affects how we sync routes. We shall * not change it while the device is active, hence, cache it. */ - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { if (priv->v4_route_table_initialized) return priv->v4_route_table; } else { @@ -1312,7 +1350,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) gint64 v; v = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, - addr_family == AF_INET + NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.route-table") : NM_CON_DEFAULT("ipv6.route-table"), self, @@ -1348,7 +1386,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) if (klass->coerce_route_table) route_table = klass->coerce_route_table(self, addr_family, route_table, is_user_config); - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { priv->v4_route_table_initialized = TRUE; priv->v4_route_table = route_table; } else { @@ -1358,7 +1396,7 @@ _prop_get_ipvx_route_table(NMDevice *self, int addr_family) _LOGT(LOGD_DEVICE, "ipv%c.route-table = %u%s", - addr_family == AF_INET ? '4' : '6', + nm_utils_addr_family_to_char(addr_family), (guint)(route_table ?: RT_TABLE_MAIN), route_table != 0u ? "" : " (policy routing not enabled)"); @@ -1437,7 +1475,7 @@ _prop_get_ipvx_dhcp_timeout(NMDevice *self, int addr_family) goto out; timeout = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, - addr_family == AF_INET + NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.dhcp-timeout") : NM_CON_DEFAULT("ipv6.dhcp-timeout"), self, @@ -1468,6 +1506,7 @@ out: * @self: the #NMDevice * @addr_family: the address family * @connection: the connection + * @log_silent: whether to log the result. * @out_is_explicit: on return, %TRUE if the user set a valid IAID in * the connection or in global configuration; %FALSE if the connection * property was empty and no valid global configuration was provided. @@ -1478,8 +1517,10 @@ static guint32 _prop_get_ipvx_dhcp_iaid(NMDevice * self, int addr_family, NMConnection *connection, + gboolean log_silent, gboolean * out_is_explicit) { + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMSettingIPConfig *s_ip; const char * iaid_str; gs_free char * iaid_str_free = NULL; @@ -1493,18 +1534,19 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, if (!iaid_str) { iaid_str_free = nm_config_data_get_connection_default( NM_CONFIG_GET_DATA, - addr_family == AF_INET ? NM_CON_DEFAULT("ipv4.dhcp-iaid") - : NM_CON_DEFAULT("ipv6.dhcp-iaid"), + IS_IPv4 ? NM_CON_DEFAULT("ipv4.dhcp-iaid") : NM_CON_DEFAULT("ipv6.dhcp-iaid"), self); iaid_str = iaid_str_free; if (!iaid_str) { iaid_str = NM_IAID_IFNAME; is_explicit = FALSE; } else if (!_nm_utils_iaid_verify(iaid_str, NULL)) { - _LOGW(LOGD_DEVICE, - "invalid global default '%s' for ipv%c.dhcp-iaid", - iaid_str, - nm_utils_addr_family_to_char(addr_family)); + if (!log_silent) { + _LOGW(LOGD_DEVICE, + "invalid global default '%s' for ipv%c.dhcp-iaid", + iaid_str, + nm_utils_addr_family_to_char(addr_family)); + } iaid_str = NM_IAID_IFNAME; is_explicit = FALSE; } @@ -1578,23 +1620,25 @@ _prop_get_ipvx_dhcp_iaid(NMDevice * self, out_fail: nm_assert(fail_reason); - _LOGW(addr_family == AF_INET ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4) - : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6), - "ipv%c.dhcp-iaid: failure to generate IAID: %s. Using interface-name based IAID", - nm_utils_addr_family_to_char(addr_family), - fail_reason); + if (!log_silent) { + _LOGW(LOGD_DEVICE | LOGD_DHCPX(IS_IPv4) | LOGD_IPX(IS_IPv4), + "ipv%c.dhcp-iaid: failure to generate IAID: %s. Using interface-name based IAID", + nm_utils_addr_family_to_char(addr_family), + fail_reason); + } is_explicit = FALSE; iface = nm_device_get_ip_iface(self); iaid = nm_utils_create_dhcp_iaid(TRUE, (const guint8 *) iface, strlen(iface)); out_good: - _LOGD(addr_family == AF_INET ? (LOGD_DEVICE | LOGD_DHCP4 | LOGD_IP4) - : (LOGD_DEVICE | LOGD_DHCP6 | LOGD_IP6), - "ipv%c.dhcp-iaid: using %u (0x%08x) IAID (str: '%s', explicit %d)", - nm_utils_addr_family_to_char(addr_family), - iaid, - iaid, - iaid_str, - is_explicit); + if (!log_silent) { + _LOGD(LOGD_DEVICE | LOGD_DHCPX(IS_IPv4) | LOGD_IPX(IS_IPv4), + "ipv%c.dhcp-iaid: using %u (0x%08x) IAID (str: '%s', explicit %d)", + nm_utils_addr_family_to_char(addr_family), + iaid, + iaid, + iaid_str, + is_explicit); + } NM_SET_OUT(out_is_explicit, is_explicit); return iaid; } @@ -1622,8 +1666,8 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) flags = nm_config_data_get_connection_default_int64( NM_CONFIG_GET_DATA, - addr_family == AF_INET ? NM_CON_DEFAULT("ipv4.dhcp-hostname-flags") - : NM_CON_DEFAULT("ipv6.dhcp-hostname-flags"), + NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.dhcp-hostname-flags") + : NM_CON_DEFAULT("ipv6.dhcp-hostname-flags"), self, 0, NM_DHCP_HOSTNAME_FLAG_FQDN_CLEAR_FLAGS, @@ -1631,9 +1675,9 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) if (!_nm_utils_validate_dhcp_hostname_flags(flags, addr_family, &error)) { _LOGW(LOGD_DEVICE, - "invalid global default value 0x%x for ipv%d.%s: %s", + "invalid global default value 0x%x for ipv%c.%s: %s", (guint) flags, - addr_family == AF_INET ? 4 : 6, + nm_utils_addr_family_to_char(addr_family), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME_FLAGS, error->message); flags = NM_DHCP_HOSTNAME_FLAG_NONE; @@ -1642,7 +1686,7 @@ _prop_get_ipvx_dhcp_hostname_flags(NMDevice *self, int addr_family) if (flags != NM_DHCP_HOSTNAME_FLAG_NONE) return flags; - if (addr_family == AF_INET) + if (NM_IS_IPv4(addr_family)) return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP4; else return NM_DHCP_HOSTNAME_FLAGS_FQDN_DEFAULT_IP6; @@ -1752,12 +1796,37 @@ _prop_get_ipv4_dhcp_client_id(NMDevice *self, NMConnection *connection, GBytes * } if (nm_streq(client_id, "duid")) { - guint32 iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET, connection, NULL); + guint32 iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET, connection, FALSE, NULL); result = nm_utils_dhcp_client_id_systemd_node_specific(iaid); goto out_good; } + if (nm_streq(client_id, "ipv6-duid")) { + gs_unref_bytes GBytes *duid = NULL; + gboolean iaid_is_explicit; + guint32 iaid; + const guint8 * duid_arr; + gsize duid_len; + + iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET, connection, FALSE, &iaid_is_explicit); + if (!iaid_is_explicit) + iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, FALSE, &iaid_is_explicit); + + duid = _prop_get_ipv6_dhcp_duid(self, connection, hwaddr, NULL); + + nm_assert(duid); + + duid_arr = g_bytes_get_data(duid, &duid_len); + + nm_assert(duid_arr); + nm_assert(duid_len >= 2u + 1u); + nm_assert(duid_len <= 2u + 128u); + + result = nm_utils_dhcp_client_id_duid(iaid, duid_arr, duid_len); + goto out_good; + } + if (nm_streq(client_id, "stable")) { nm_auto_free_checksum GChecksum *sum = NULL; guint8 digest[NM_UTILS_CHECKSUM_LENGTH_SHA1]; @@ -2338,8 +2407,8 @@ nm_device_ip_config_new(NMDevice *self, int addr_family) { nm_assert_addr_family(addr_family); - return addr_family == AF_INET ? (gpointer) nm_device_ip4_config_new(self) - : (gpointer) nm_device_ip6_config_new(self); + return NM_IS_IPv4(addr_family) ? (gpointer) nm_device_ip4_config_new(self) + : (gpointer) nm_device_ip6_config_new(self); } NML3ConfigData * @@ -2754,7 +2823,7 @@ static void _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); nm_assert_addr_family(addr_family); @@ -2775,7 +2844,7 @@ _set_ip_state(NMDevice *self, int addr_family, NMDeviceIPState new_state) * * This is not documented/guaranteed behavior, but seems to make sense for now. */ _active_connection_set_state_flags(self, - addr_family == AF_INET + NM_IS_IPv4(addr_family) ? NM_ACTIVATION_STATE_FLAG_IP4_READY : NM_ACTIVATION_STATE_FLAG_IP6_READY); } @@ -2820,6 +2889,8 @@ _set_ifindex(NMDevice *self, int ifindex, gboolean is_ip_ifindex) if (!is_ip_ifindex) _notify(self, PROP_IFINDEX); + if (priv->manager) + nm_manager_emit_device_ifindex_changed(priv->manager, self); return TRUE; } @@ -3559,7 +3630,7 @@ static gboolean default_route_metric_penalty_detect(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); /* currently we don't differentiate between IPv4 and IPv6 when detecting * connectivity. */ @@ -3575,10 +3646,8 @@ default_route_metric_penalty_get(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - nm_assert_addr_family(addr_family); - - if (addr_family == AF_INET ? priv->default_route_metric_penalty_ip4_has - : priv->default_route_metric_penalty_ip6_has) + if (NM_IS_IPv4(addr_family) ? priv->default_route_metric_penalty_ip4_has + : priv->default_route_metric_penalty_ip6_has) return 20000; return 0; } @@ -3612,8 +3681,8 @@ nm_device_get_route_metric(NMDevice *self, int addr_family) /* use the current NMConfigData, which makes this configuration reloadable. * Note that that means that the route-metric might change between SIGHUP. * You must cache the returned value if that is a problem. */ - property = addr_family == AF_INET ? NM_CON_DEFAULT("ipv4.route-metric") - : NM_CON_DEFAULT("ipv6.route-metric"); + property = NM_IS_IPv4(addr_family) ? NM_CON_DEFAULT("ipv4.route-metric") + : NM_CON_DEFAULT("ipv6.route-metric"); route_metric = nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, property, self, @@ -3644,7 +3713,8 @@ nm_device_get_route_table(NMDevice *self, int addr_family) static NMIPRouteTableSyncMode _get_route_table_sync_mode_stateful(NMDevice *self, int addr_family) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMDedupMultiIter ipconf_iter; gboolean all_sync_now; gboolean all_sync_eff; @@ -3652,25 +3722,14 @@ _get_route_table_sync_mode_stateful(NMDevice *self, int addr_family) all_sync_now = _prop_get_ipvx_route_table(self, addr_family) != 0u; if (!all_sync_now) { + const NMPlatformIPRoute *route; + /* If there's a local route switch to all-sync in order * to properly manage the local table */ - if (addr_family == AF_INET) { - const NMPlatformIP4Route *route; - - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, priv->con_ip_config_4, &route) { - if (nm_platform_route_type_uncoerce(route->type_coerced) == RTN_LOCAL) { - all_sync_now = TRUE; - break; - } - } - } else { - const NMPlatformIP6Route *route; - - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, priv->con_ip_config_6, &route) { - if (nm_platform_route_type_uncoerce(route->type_coerced) == RTN_LOCAL) { - all_sync_now = TRUE; - break; - } + 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; } } } @@ -3685,13 +3744,13 @@ _get_route_table_sync_mode_stateful(NMDevice *self, int addr_family) * The purpose of this is to support reapply of route-table (and thus the * all-sync mode). If reapply toggles from all-sync to no-all-sync, we must * sync one last time. */ - if (addr_family == AF_INET) + if (NM_IS_IPv4(addr_family)) all_sync_eff = priv->v4_route_table_all_sync_before; else all_sync_eff = priv->v6_route_table_all_sync_before; } - if (addr_family == AF_INET) + if (NM_IS_IPv4(addr_family)) priv->v4_route_table_all_sync_before = all_sync_now; else priv->v6_route_table_all_sync_before = all_sync_now; @@ -3762,8 +3821,11 @@ get_type_description(NMDevice *self) gs_free char *s = NULL; typename = G_OBJECT_TYPE_NAME(self); - if (g_str_has_prefix(typename, "NMDevice")) + if (g_str_has_prefix(typename, "NMDevice")) { typename += 8; + if (nm_streq(typename, "Veth")) + typename = "Ethernet"; + } s = g_ascii_strdown(typename, -1); klass->default_type_description = g_intern_string(s); klass->default_type_description_klass = klass; @@ -3943,7 +4005,7 @@ concheck_periodic_schedule_do(NMDevice *self, int addr_family, gint64 now_ns) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gboolean periodic_check_disabled = FALSE; gint64 expiry, tdiff; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); /* we always cancel whatever was pending. */ if (nm_clear_g_source(&priv->concheck_x[IS_IPv4].p_cur_id)) @@ -3998,7 +4060,7 @@ concheck_periodic_schedule_set(NMDevice *self, int addr_family, ConcheckSchedule NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); gint64 new_expiry, exp_expiry, cur_expiry, tdiff; gint64 now_ns = 0; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); if (priv->concheck_x[IS_IPv4].p_max_interval == 0) { /* periodic check is disabled. Nothing to do. */ @@ -4158,7 +4220,7 @@ concheck_update_interval(NMDevice *self, int addr_family, gboolean check_now) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); guint new_interval; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); new_interval = nm_connectivity_get_interval(concheck_get_mgr(self)); @@ -4202,7 +4264,7 @@ concheck_update_state(NMDevice * self, gboolean allow_periodic_bump) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); /* @state is a result of the connectivity check. We only expect a precise * number of possible values. */ @@ -4283,14 +4345,14 @@ nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) NMDeviceClass *klass; NMConnection * connection = nm_device_get_applied_connection(self); const char * method; + const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_val_if_fail(NM_IS_CONNECTION(connection), "" /* bogus */); - nm_assert_addr_family(addr_family); method = nm_utils_get_ip_config_method(connection, addr_family); - if ((addr_family == AF_INET && nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) - || (addr_family == AF_INET6 && nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO))) { + if ((IS_IPv4 && nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + || (!IS_IPv4 && nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_AUTO))) { klass = NM_DEVICE_GET_CLASS(self); if (klass->get_auto_ip_config_method) { const char *auto_method; @@ -4307,7 +4369,7 @@ nm_device_get_effective_ip_config_method(NMDevice *self, int addr_family) static void concheck_handle_complete(NMDeviceConnectivityHandle *handle, GError *error) { - const gboolean IS_IPv4 = (handle->addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(handle->addr_family); /* The moment we invoke the callback, we unlink it. It signals * that @handle is handled -- as far as the callee of callback @@ -4495,7 +4557,7 @@ concheck_start(NMDevice * self, (long long unsigned) handle->seq, is_periodic ? ", periodic-check" : ""); - if (addr_family == AF_INET && !priv->concheck_rp_filter_checked) { + if (NM_IS_IPv4(addr_family) && !priv->concheck_rp_filter_checked) { if ((ifname = nm_device_get_ip_iface_from_platform(self))) { gboolean due_to_all; int val; @@ -4560,17 +4622,15 @@ NMConnectivityState nm_device_get_connectivity_state(NMDevice *self, int addr_family) { NMDevicePrivate *priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); g_return_val_if_fail(NM_IS_DEVICE(self), NM_CONNECTIVITY_UNKNOWN); - nm_assert_addr_family(addr_family); priv = NM_DEVICE_GET_PRIVATE(self); switch (addr_family) { case AF_INET: case AF_INET6: - return priv->concheck_x[IS_IPv4].state; + return priv->concheck_x[NM_IS_IPv4(addr_family)].state; default: nm_assert(addr_family == AF_UNSPEC); return NM_MAX_WITH_CMP(nm_connectivity_state_cmp, @@ -4653,10 +4713,10 @@ nm_device_master_enslave_slave(NMDevice *self, NMDevice *slave, NMConnection *co */ if (success) { if (priv->ip_state_4 == NM_DEVICE_IP_STATE_WAIT) - nm_device_activate_stage3_ip4_start(self); + nm_device_activate_stage3_ip_start(self, AF_INET); if (priv->ip_state_6 == NM_DEVICE_IP_STATE_WAIT) - nm_device_activate_stage3_ip6_start(self); + nm_device_activate_stage3_ip_start(self, AF_INET6); } /* Since slave devices don't have their own IP configuration, @@ -4716,7 +4776,7 @@ nm_device_master_release_one_slave(NMDevice * self, nm_assert(slave == info->slave); /* first, let subclasses handle the release ... */ - if (info->slave_is_enslaved || force) + if (info->slave_is_enslaved || nm_device_sys_iface_state_is_external(slave) || force) NM_DEVICE_GET_CLASS(self)->release_slave(self, slave, configure); /* raise notifications about the release, including clearing is_enslaved. */ @@ -4887,9 +4947,9 @@ carrier_changed(NMDevice *self, gboolean carrier) /* If needed, also resume IP configuration that is * waiting for carrier. */ if (nm_device_activate_ip4_state_in_wait(self)) - nm_device_activate_stage3_ip4_start(self); + nm_device_activate_stage3_ip_start(self, AF_INET); if (nm_device_activate_ip6_state_in_wait(self)) - nm_device_activate_stage3_ip6_start(self); + nm_device_activate_stage3_ip_start(self, AF_INET6); return; } /* fall-through and change state of device */ @@ -5051,7 +5111,7 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) g_return_if_fail(plink); if (plink->master <= 0) - return; + goto out; master = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, plink->master); plink_master = nm_platform_link_get(nm_device_get_platform(self), plink->master); @@ -5060,15 +5120,17 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) if (master == NULL && plink_master && nm_streq0(plink_master->name, "ovs-system") && plink_master->type == NM_LINK_TYPE_OPENVSWITCH) { _LOGD(LOGD_DEVICE, "the device claimed by openvswitch"); - return; + goto out; } + priv->master_ifindex = plink->master; + if (priv->master) { if (plink->master > 0 && plink->master == nm_device_get_ifindex(priv->master)) { /* call add-slave again. We expect @self already to be added to * the master, but this also triggers a recheck-assume. */ nm_device_master_add_slave(priv->master, self, FALSE); - return; + goto out; } nm_device_master_release_one_slave(priv->master, @@ -5078,43 +5140,72 @@ device_recheck_slave_status(NMDevice *self, const NMPlatformLink *plink) NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } - if (master && NM_DEVICE_GET_CLASS(master)->enslave_slave) + if (master && NM_DEVICE_GET_CLASS(master)->enslave_slave) { nm_device_master_add_slave(master, self, FALSE); - else if (master) { - _LOGI(LOGD_DEVICE, + goto out; + } + + if (master) { + _LOGD(LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring", nm_device_get_iface(master)); } else { - _LOGW(LOGD_DEVICE, + _LOGD(LOGD_DEVICE, "enslaved to unknown device %d (%s%s%s)", plink->master, NM_PRINT_FMT_QUOTED(plink_master, "\"", plink_master->name, "\"", "??")); } + if (!priv->ifindex_changed_id) { + priv->ifindex_changed_id = g_signal_connect(nm_device_get_manager(self), + NM_MANAGER_DEVICE_IFINDEX_CHANGED, + G_CALLBACK(device_ifindex_changed_cb), + self); + } + return; + +out: + nm_clear_g_signal_handler(nm_device_get_manager(self), &priv->ifindex_changed_id); +} + +static void +device_ifindex_changed_cb(NMManager *manager, NMDevice *device_changed, NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + + if (priv->master_ifindex != nm_device_get_ifindex(device_changed)) + return; + + _LOGD(LOGD_DEVICE, + "master %s with ifindex %d appeared", + nm_device_get_iface(device_changed), + nm_device_get_ifindex(device_changed)); + if (!priv->device_link_changed_id) + priv->device_link_changed_id = g_idle_add((GSourceFunc) device_link_changed, self); } static void ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - gint32 now; - GArray * addresses, *dns_servers, *dns_domains; - guint len, i; + 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; if (nm_ndisc_get_node_type(ndisc) != NM_NDISC_NODE_TYPE_ROUTER) return; - now = nm_utils_get_monotonic_timestamp_sec(); - 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, preferred; - gint32 base; + guint32 lifetime; + guint32 preferred; if (IN6_IS_ADDR_UNSPECIFIED(&addr->address) || IN6_IS_ADDR_LINKLOCAL(&addr->address)) continue; @@ -5125,31 +5216,21 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) if (addr->plen != 64) continue; - /* resolve the timestamps relative to a new base. - * - * Note that for convenience, platform @addr might have timestamp and/or - * lifetime unset. We don't allow that flexibility for ndisc and require - * well defined timestamps. */ - if (addr->timestamp) { - nm_assert(addr->timestamp < G_MAXINT32); - base = addr->timestamp; - } else - base = now; - lifetime = nm_utils_lifetime_get(addr->timestamp, addr->lifetime, addr->preferred, - base, + 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->timestamp = base; - ndisc_addr->lifetime = lifetime; - ndisc_addr->preferred = preferred; + 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); @@ -5159,10 +5240,10 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) 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->timestamp = now; - ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME; + 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); @@ -5172,16 +5253,13 @@ ndisc_set_router_config(NMNDisc *ndisc, NMDevice *self) 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->timestamp = now; - ndisc_search->lifetime = NM_NDISC_ROUTER_LIFETIME; + 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); } nm_ndisc_set_config(ndisc, addresses, dns_servers, dns_domains); - g_array_unref(addresses); - g_array_unref(dns_servers); - g_array_unref(dns_domains); } static void @@ -5776,7 +5854,7 @@ sriov_op_queue_op(NMDevice *self, SriovOp *op) static void sriov_op_queue(NMDevice * self, guint num_vfs, - NMTernary autoprobe, + NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer callback_data) { @@ -5825,7 +5903,7 @@ device_init_static_sriov_num_vfs(NMDevice *self) NULL); num_vfs = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXINT32, -1); if (num_vfs >= 0) - sriov_op_queue(self, num_vfs, NM_TERNARY_DEFAULT, NULL, NULL); + sriov_op_queue(self, num_vfs, NM_OPTION_BOOL_DEFAULT, NULL, NULL); } } @@ -5883,7 +5961,6 @@ realize_start_setup(NMDevice * self, NMDevicePrivate * priv; NMDeviceClass * klass; NMPlatform * platform; - static guint32 id = 0; NMDeviceCapabilities capabilities = 0; NMConfig * config; guint real_rate; @@ -5969,7 +6046,12 @@ realize_start_setup(NMDevice * self, if (!priv->udi) { /* Use a placeholder UDI until we get a real one */ - priv->udi = g_strdup_printf("/virtual/device/placeholder/%d", id++); + if (priv->udi_id == 0) { + static guint64 udi_id_counter = 0; + + priv->udi_id = ++udi_id_counter; + } + priv->udi = g_strdup_printf("/virtual/device/placeholder/%" G_GUINT64_FORMAT, priv->udi_id); _notify(self, PROP_UDI); } @@ -6153,6 +6235,8 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) if (nm_clear_g_free(&priv->ip_iface_)) _notify(self, PROP_IP_IFACE); + priv->master_ifindex = 0; + _set_mtu(self, 0); if (priv->driver_version) { @@ -6193,6 +6277,7 @@ nm_device_unrealize(NMDevice *self, gboolean remove_resources, GError **error) _notify(self, PROP_CAPABILITIES); nm_clear_g_signal_handler(nm_config_get(), &priv->config_changed_id); + nm_clear_g_signal_handler(priv->manager, &priv->ifindex_changed_id); priv->real = FALSE; _notify(self, PROP_REAL); @@ -6444,7 +6529,7 @@ nm_device_master_check_slave_physical_port(NMDevice *self, NMDevice *slave, NMLo } /* release all slaves */ -static void +void nm_device_master_release_slaves(NMDevice *self) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); @@ -7659,7 +7744,7 @@ static void activation_source_clear(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); if (priv->activation_source_id_x[IS_IPv4] != 0) { _LOGD(LOGD_DEVICE, @@ -7676,7 +7761,7 @@ static gboolean activation_source_handle_cb(NMDevice *self, int addr_family) { NMDevicePrivate * priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); ActivationHandleFunc activation_source_func; guint activation_source_id; @@ -7726,7 +7811,7 @@ static void activation_source_schedule(NMDevice *self, ActivationHandleFunc func, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); guint new_id = 0; if (priv->activation_source_id_x[IS_IPv4] != 0 @@ -7769,7 +7854,7 @@ static void activation_source_invoke_sync(NMDevice *self, ActivationHandleFunc func, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); if (priv->activation_source_id_x[IS_IPv4] == 0) { _LOGD(LOGD_DEVICE, @@ -7923,13 +8008,13 @@ sriov_vf_config_to_platform(NMDevice *self, NMSriovVF *vf, GError **error) } static void -sriov_params_cb(GError *error, gpointer data) +sriov_params_cb(GError *error, gpointer user_data) { NMDevice * self; NMDevicePrivate *priv; nm_auto_freev NMPlatformVF **plat_vfs = NULL; - nm_utils_user_data_unpack(data, &self, &plat_vfs); + nm_utils_user_data_unpack(user_data, &self, &plat_vfs); if (nm_utils_error_is_cancelled_or_disposing(error)) return; @@ -7998,7 +8083,8 @@ activate_stage1_device_prepare(NMDevice *self) gs_free_error GError *error = NULL; NMSriovVF * vf; NMTernary autoprobe; - guint i, num; + guint num; + guint i; autoprobe = nm_setting_sriov_get_autoprobe_drivers(s_sriov); if (autoprobe == NM_TERNARY_DEFAULT) { @@ -8006,9 +8092,9 @@ activate_stage1_device_prepare(NMDevice *self) NM_CONFIG_GET_DATA, NM_CON_DEFAULT("sriov.autoprobe-drivers"), self, - NM_TERNARY_FALSE, - NM_TERNARY_TRUE, - NM_TERNARY_TRUE); + NM_OPTION_BOOL_FALSE, + NM_OPTION_BOOL_TRUE, + NM_OPTION_BOOL_TRUE); } num = nm_setting_sriov_get_num_vfs(s_sriov); @@ -8035,7 +8121,7 @@ activate_stage1_device_prepare(NMDevice *self) */ sriov_op_queue(self, nm_setting_sriov_get_total_vfs(s_sriov), - autoprobe, + NM_TERNARY_TO_OPTION_BOOL(autoprobe), sriov_params_cb, nm_utils_user_data_pack(self, g_steal_pointer(&plat_vfs))); priv->stage1_sriov_state = NM_DEVICE_STAGE_STATE_PENDING; @@ -8758,7 +8844,7 @@ ensure_con_ip_config(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMConnection * connection; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMIPConfig * con_ip_config; if (priv->con_ip_config_x[IS_IPv4]) @@ -8835,7 +8921,7 @@ ip_config_merge_and_apply(NMDevice *self, int addr_family, gboolean commit) gboolean ignore_default_routes = FALSE; GSList * iter; const char * ip6_addr_gen_token = NULL; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); if (nm_device_sys_iface_state_is_external(self)) commit = FALSE; @@ -9079,12 +9165,12 @@ static gboolean dhcp_grace_period_expired(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + 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; - _LOGI(LOGD_DHCP_from_addr_family(addr_family), + _LOGI(LOGD_DHCPX(IS_IPv4), "DHCPv%c: grace period expired", nm_utils_addr_family_to_char(addr_family)); @@ -9110,7 +9196,7 @@ static gboolean dhcp_grace_period_start(NMDevice *self, int addr_family) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); guint32 timeout; /* In any other case (expired lease, assumed connection, etc.), @@ -9125,12 +9211,12 @@ dhcp_grace_period_start(NMDevice *self, int addr_family) * by a constant factor. */ timeout = _prop_get_ipvx_dhcp_timeout(self, addr_family); if (timeout == NM_DHCP_TIMEOUT_INFINITY) - _LOGI(LOGD_DHCP_from_addr_family(addr_family), + _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_DHCP_from_addr_family(addr_family), + _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); @@ -9434,7 +9520,7 @@ connection_ip_method_requires_carrier(NMConnection *connection, method = nm_utils_get_ip_config_method(connection, addr_family); - if (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { NM_SET_OUT(out_ip_enabled, !nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)); return NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO, @@ -9778,7 +9864,7 @@ dhcp6_start_with_link_ready(NMDevice *self, NMConnection *connection) if (pllink) hwaddr = nmp_link_address_get_as_bytes(&pllink->l_address); - iaid = _prop_get_ipvx_dhcp_iaid(self, AF_INET6, connection, &iaid_explicit); + 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( @@ -9862,13 +9948,16 @@ 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); @@ -10969,7 +11058,7 @@ ip_requires_slaves(NMDevice *self, int addr_family) method = nm_device_get_effective_ip_config_method(self, addr_family); - if (addr_family == AF_INET) + if (NM_IS_IPv4(addr_family)) return nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_AUTO); /* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves) @@ -10986,7 +11075,7 @@ act_stage3_ip_config_start(NMDevice * self, gpointer * out_config, NMDeviceStateReason *out_failure_reason) { - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMConnection * connection; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; @@ -11208,103 +11297,62 @@ act_stage3_ip_config_start(NMDevice * self, } } -/** - * nm_device_activate_stage3_ip4_start: - * @self: the device - * - * Try starting IPv4 configuration. - */ gboolean -nm_device_activate_stage3_ip4_start(NMDevice *self) +nm_device_activate_stage3_ip_start(NMDevice *self, int addr_family) { - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); + 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 NMIP4Config *ip4_config = NULL; + NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + gs_unref_object NMIPConfig *ip_config = NULL; - g_assert(priv->ip_state_4 == NM_DEVICE_IP_STATE_WAIT); + g_assert(priv->ip_state_x[IS_IPv4] == NM_DEVICE_IP_STATE_WAIT); if (nm_device_sys_iface_state_is_external(self)) { - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE); check_ip_state(self, FALSE, TRUE); return TRUE; } - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_CONF); - ret = NM_DEVICE_GET_CLASS(self)->act_stage3_ip_config_start(self, - AF_INET, - (gpointer *) &ip4_config, - &failure_reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) - nm_device_activate_schedule_ip_config_result(self, AF_INET, NM_IP_CONFIG_CAST(ip4_config)); - else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); - return FALSE; - } else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) { - /* Activation not wanted */ - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_FAIL); - } else if (ret == NM_ACT_STAGE_RETURN_IP_WAIT) { - /* Wait for something to try IP config again */ - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); - } else - g_assert(ret == NM_ACT_STAGE_RETURN_POSTPONE); - - return TRUE; -} + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_CONF); -/** - * nm_device_activate_stage3_ip6_start: - * @self: the device - * - * Try starting IPv6 configuration. - */ -gboolean -nm_device_activate_stage3_ip6_start(NMDevice *self) -{ - NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - NMActStageReturn ret; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - gs_unref_object NMIP6Config *ip6_config = NULL; - - g_assert(priv->ip_state_6 == NM_DEVICE_IP_STATE_WAIT); - - if (nm_device_sys_iface_state_is_external(self)) { - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - return TRUE; - } - - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF); ret = NM_DEVICE_GET_CLASS(self)->act_stage3_ip_config_start(self, - AF_INET6, - (gpointer *) &ip6_config, + addr_family, + (gpointer *) &ip_config, &failure_reason); - if (ret == NM_ACT_STAGE_RETURN_SUCCESS) { - if (!ip6_config) - ip6_config = nm_device_ip6_config_new(self); - /* Here we get a static IPv6 config, like for Shared where it's - * autogenerated or from modems where it comes from ModemManager. - */ - nm_assert(!applied_config_get_current(&priv->ac_ip6_config)); - applied_config_init(&priv->ac_ip6_config, ip6_config); - nm_device_activate_schedule_ip_config_result(self, AF_INET6, NULL); - } else if (ret == NM_ACT_STAGE_RETURN_IP_DONE) { - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); + + 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); + break; + case NM_ACT_STAGE_RETURN_IP_DONE: + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_DONE); check_ip_state(self, FALSE, TRUE); - } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + break; + case NM_ACT_STAGE_RETURN_FAILURE: nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); return FALSE; - } else if (ret == NM_ACT_STAGE_RETURN_IP_FAIL) { + case NM_ACT_STAGE_RETURN_IP_FAIL: /* Activation not wanted */ - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_FAIL); - } else if (ret == NM_ACT_STAGE_RETURN_IP_WAIT) { + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL); + break; + case NM_ACT_STAGE_RETURN_IP_WAIT: /* Wait for something to try IP config again */ - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); - } else + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT); + break; + default: g_assert(ret == NM_ACT_STAGE_RETURN_POSTPONE); + } return TRUE; } @@ -11334,12 +11382,12 @@ activate_stage3_ip_config_start(NMDevice *self) "interface %s not up for IP configuration", nm_device_get_ip_iface(self)); - /* IPv4 */ - if (nm_device_activate_ip4_state_in_wait(self) && !nm_device_activate_stage3_ip4_start(self)) + if (nm_device_activate_ip4_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET)) return; - /* IPv6 */ - if (nm_device_activate_ip6_state_in_wait(self) && !nm_device_activate_stage3_ip6_start(self)) + if (nm_device_activate_ip6_state_in_wait(self) + && !nm_device_activate_stage3_ip_start(self, AF_INET6)) return; /* Proxy */ @@ -11438,28 +11486,31 @@ void nm_device_activate_schedule_stage3_ip_config_start(NMDevice *self) { NMDevicePrivate *priv; + int ifindex; g_return_if_fail(NM_IS_DEVICE(self)); priv = NM_DEVICE_GET_PRIVATE(self); g_return_if_fail(priv->act_request.obj); + ifindex = nm_device_get_ip_ifindex(self); /* Add the interface to the specified firewall zone */ if (priv->fw_state == FIREWALL_STATE_UNMANAGED) { - if (!nm_device_sys_iface_state_is_external(self)) { + if (nm_device_sys_iface_state_is_external(self)) { + /* fake success */ + priv->fw_state = FIREWALL_STATE_INITIALIZED; + } else if (ifindex > 0) { priv->fw_state = FIREWALL_STATE_WAIT_STAGE_3; fw_change_zone(self); return; } - - /* fake success. */ - priv->fw_state = FIREWALL_STATE_INITIALIZED; + /* no ifindex, nothing to do for now */ } else if (priv->fw_state == FIREWALL_STATE_WAIT_STAGE_3) { /* a firewall call for stage3 is pending. Return and wait. */ return; } - nm_assert(priv->fw_state == FIREWALL_STATE_INITIALIZED); + nm_assert(ifindex <= 0 || priv->fw_state == FIREWALL_STATE_INITIALIZED); activation_source_schedule(self, activate_stage3_ip_config_start, AF_INET); } @@ -11479,37 +11530,45 @@ act_stage4_ip_config_timeout(NMDevice * self, return NM_ACT_STAGE_RETURN_SUCCESS; } -/* - * nm_device_activate_stage4_ip4_config_timeout - * - * Time out on retrieving the IPv4 config. - * - */ static void -activate_stage4_ip_config_timeout_4(NMDevice *self) +activate_stage4_ip_config_timeout_x(NMDevice *self, int addr_family) { - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; + NMActStageReturn ret; + + ret = + NM_DEVICE_GET_CLASS(self)->act_stage4_ip_config_timeout(self, addr_family, &failure_reason); - ret = NM_DEVICE_GET_CLASS(self)->act_stage4_ip_config_timeout(self, AF_INET, &failure_reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) return; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); return; } g_assert(ret == NM_ACT_STAGE_RETURN_SUCCESS); - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_FAIL); - + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_FAIL); check_ip_state(self, FALSE, TRUE); } +static void +activate_stage4_ip_config_timeout_4(NMDevice *self) +{ + activate_stage4_ip_config_timeout_x(self, AF_INET); +} + +static void +activate_stage4_ip_config_timeout_6(NMDevice *self) +{ + activate_stage4_ip_config_timeout_x(self, AF_INET6); +} + void nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family) { NMDevicePrivate *priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); + 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)); @@ -11518,43 +11577,25 @@ nm_device_activate_schedule_ip_config_timeout(NMDevice *self, int addr_family) g_return_if_fail(priv->act_request.obj); - activation_source_schedule(self, activate_stage4_ip_config_timeout_x[IS_IPv4], addr_family); -} - -static void -activate_stage4_ip_config_timeout_6(NMDevice *self) -{ - NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - NMDeviceStateReason failure_reason = NM_DEVICE_STATE_REASON_NONE; - - ret = NM_DEVICE_GET_CLASS(self)->act_stage4_ip_config_timeout(self, AF_INET6, &failure_reason); - if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - return; - if (ret == NM_ACT_STAGE_RETURN_FAILURE) { - nm_device_state_changed(self, NM_DEVICE_STATE_FAILED, failure_reason); - return; - } - g_assert(ret == NM_ACT_STAGE_RETURN_SUCCESS); - - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_FAIL); - - check_ip_state(self, FALSE, TRUE); + activation_source_schedule(self, + IS_IPv4 ? activate_stage4_ip_config_timeout_4 + : activate_stage4_ip_config_timeout_6, + addr_family); } static gboolean share_init(NMDevice *self, GError **error) { - char * modules[] = {"ip_tables", - "iptable_nat", - "nf_nat_ftp", - "nf_nat_irc", - "nf_nat_sip", - "nf_nat_tftp", - "nf_nat_pptp", - "nf_nat_h323", - NULL}; - char **iter; - int errsv; + const char *const modules[] = {"ip_tables", + "iptable_nat", + "nf_nat_ftp", + "nf_nat_irc", + "nf_nat_sip", + "nf_nat_tftp", + "nf_nat_pptp", + "nf_nat_h323"}; + guint i; + int errsv; if (nm_platform_sysctl_get_int32(nm_device_get_platform(self), NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv4/ip_forward"), @@ -11592,35 +11633,24 @@ share_init(NMDevice *self, GError **error) nm_strerror_native(errsv)); } - for (iter = modules; *iter; iter++) - nm_utils_modprobe(NULL, FALSE, *iter, NULL); + for (i = 0; i < G_N_ELEMENTS(modules); i++) + nm_utils_modprobe(NULL, FALSE, modules[i], NULL); return TRUE; } -#define add_share_rule(req, table, ...) \ - G_STMT_START \ - { \ - char *_cmd = g_strdup_printf(__VA_ARGS__); \ - nm_act_request_add_share_rule(req, table, _cmd); \ - g_free(_cmd); \ - } \ - G_STMT_END - static gboolean start_sharing(NMDevice *self, NMIP4Config *config, GError **error) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); NMActRequest * req; - char str_addr[INET_ADDRSTRLEN]; - char str_mask[INET_ADDRSTRLEN]; - guint32 netmask, network; const NMPlatformIP4Address *ip4_addr = NULL; const char * ip_iface; GError * local = NULL; NMConnection * conn; NMSettingConnection * s_con; gboolean announce_android_metered; + NMUtilsShareRules * share_rules; g_return_val_if_fail(config, FALSE); @@ -11645,57 +11675,13 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) req = nm_device_get_act_request(self); g_return_val_if_fail(req, FALSE); - netmask = _nm_utils_ip4_prefix_to_netmask(ip4_addr->plen); - _nm_utils_inet4_ntop(netmask, str_mask); - - network = ip4_addr->address & netmask; - _nm_utils_inet4_ntop(network, str_addr); - - add_share_rule(req, - "nat", - "POSTROUTING --source %s/%s ! --destination %s/%s --jump MASQUERADE", - str_addr, - str_mask, - str_addr, - str_mask); - add_share_rule(req, - "filter", - "FORWARD --destination %s/%s --out-interface %s --match state --state " - "ESTABLISHED,RELATED --jump ACCEPT", - str_addr, - str_mask, - ip_iface); - add_share_rule(req, - "filter", - "FORWARD --source %s/%s --in-interface %s --jump ACCEPT", - str_addr, - str_mask, - ip_iface); - add_share_rule(req, - "filter", - "FORWARD --in-interface %s --out-interface %s --jump ACCEPT", - ip_iface, - ip_iface); - add_share_rule(req, "filter", "FORWARD --out-interface %s --jump REJECT", ip_iface); - add_share_rule(req, "filter", "FORWARD --in-interface %s --jump REJECT", ip_iface); - add_share_rule(req, - "filter", - "INPUT --in-interface %s --protocol udp --destination-port 67 --jump ACCEPT", - ip_iface); - add_share_rule(req, - "filter", - "INPUT --in-interface %s --protocol tcp --destination-port 67 --jump ACCEPT", - ip_iface); - add_share_rule(req, - "filter", - "INPUT --in-interface %s --protocol udp --destination-port 53 --jump ACCEPT", - ip_iface); - add_share_rule(req, - "filter", - "INPUT --in-interface %s --protocol tcp --destination-port 53 --jump ACCEPT", - ip_iface); - - nm_act_request_set_shared(req, TRUE); + share_rules = nm_utils_share_rules_new(); + + nm_utils_share_rules_add_all_rules(share_rules, ip_iface, ip4_addr->address, ip4_addr->plen); + + nm_utils_share_rules_apply(share_rules, TRUE); + + nm_act_request_set_shared(req, share_rules); conn = nm_act_request_get_applied_connection(req); s_con = nm_connection_get_setting_connection(conn); @@ -11730,7 +11716,7 @@ start_sharing(NMDevice *self, NMIP4Config *config, GError **error) "could not start dnsmasq due to %s", local->message); g_error_free(local); - nm_act_request_set_shared(req, FALSE); + nm_act_request_set_shared(req, NULL); return FALSE; } @@ -11798,12 +11784,14 @@ nm_device_arp_announce(NMDevice *self) } static void -activate_stage5_ip_config_result_4(NMDevice *self) +activate_stage5_ip_config_result_x(NMDevice *self, int addr_family) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + const int IS_IPv4 = NM_IS_IPv4(addr_family); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); NMActRequest * req; const char * method; int ip_ifindex; + int errsv; gboolean do_announce = FALSE; req = nm_device_get_act_request(self); @@ -11811,6 +11799,8 @@ activate_stage5_ip_config_result_4(NMDevice *self) /* Interface must be IFF_UP before IP config can be applied */ ip_ifindex = nm_device_get_ip_ifindex(self); + g_return_if_fail(ip_ifindex); + if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) && !nm_device_sys_iface_state_is_external_or_assume(self)) { nm_platform_link_set_up(nm_device_get_platform(self), ip_ifindex, NULL); @@ -11820,86 +11810,172 @@ activate_stage5_ip_config_result_4(NMDevice *self) nm_device_get_ip_iface(self)); } - if (!ip_config_merge_and_apply(self, AF_INET, TRUE)) { - _LOGD(LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + if (!ip_config_merge_and_apply(self, addr_family, TRUE)) { + _LOGD(LOGD_DEVICE | LOGD_IPX(IS_IPv4), + "Activation: Stage 5 of 5 (IPv%c Commit) failed", + nm_utils_addr_family_to_char(addr_family)); + nm_device_ip_method_failed(self, addr_family, NM_DEVICE_STATE_REASON_CONFIG_FAILED); return; } - /* Start IPv4 sharing if we need it */ - method = nm_device_get_effective_ip_config_method(self, AF_INET); - if (nm_streq(method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) { - gs_free_error GError *error = NULL; + if (!IS_IPv4) { + if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE + && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) { + if (applied_config_get_current(&priv->dhcp6.ip6_config)) { + /* If IPv6 wasn't the first IP to complete, and DHCP was used, + * then ensure dispatcher scripts get the DHCP lease information. + */ + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, + self, + NULL, + NULL, + NULL, + NULL); + } else { + /* still waiting for first dhcp6 lease. */ + return; + } + } + } - if (!start_sharing(self, priv->ip_config_4, &error)) { - _LOGW(LOGD_SHARING, - "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s", - error->message); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - return; + /* Start IPv4 sharing/IPv6 forwarding if we need it */ + method = nm_device_get_effective_ip_config_method(self, addr_family); + if (IS_IPv4) { + 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)) { + _LOGW(LOGD_SHARING, + "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed: %s", + error->message); + nm_device_ip_method_failed(self, + AF_INET, + NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + return; + } + } + } else { + if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { + if (!nm_platform_sysctl_set( + nm_device_get_platform(self), + NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"), + "1")) { + errsv = errno; + _LOGE(LOGD_SHARING, + "share: error enabling IPv6 forwarding: (%d) %s", + errsv, + nm_strerror_native(errsv)); + nm_device_ip_method_failed(self, + AF_INET6, + NM_DEVICE_STATE_REASON_SHARED_START_FAILED); + return; + } } } - if (priv->dhcp_data_4.client) { - gs_free_error GError *error = NULL; + if (IS_IPv4) { + if (priv->dhcp_data_4.client) { + gs_free_error GError *error = NULL; - if (!nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) { - _LOGW(LOGD_DHCP4, - "Activation: Stage 5 of 5 (IPv4 Commit) error accepting lease: %s", - error->message); - nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_DHCP_ERROR); - return; + if (!nm_dhcp_client_accept(priv->dhcp_data_4.client, &error)) { + _LOGW(LOGD_DHCP4, + "Activation: Stage 5 of 5 (IPv4 Commit) error accepting lease: %s", + error->message); + nm_device_ip_method_failed(self, AF_INET, NM_DEVICE_STATE_REASON_DHCP_ERROR); + return; + } + } + + /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure + * dispatcher scripts get the DHCP lease information. + */ + if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self) + && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) { + nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, + self, + NULL, + NULL, + NULL, + NULL); } } - /* If IPv4 wasn't the first to complete, and DHCP was used, then ensure - * dispatcher scripts get the DHCP lease information. - */ - if (priv->dhcp_data_4.client && nm_device_activate_ip4_state_in_conf(self) - && (nm_device_get_state(self) > NM_DEVICE_STATE_IP_CONFIG)) { - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP4_CHANGE, self, NULL, NULL, NULL, NULL); + if (!IS_IPv4) { + /* Check if we have to wait for DAD */ + if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && !priv->dad6_ip6_config) { + if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail(self, AF_INET6)) + _LOGI(LOGD_DEVICE | LOGD_IP6, + "IPv6 DAD: carrier missing and ignored, not delaying activation"); + else + priv->dad6_ip6_config = dad6_get_pending_addresses(self); + + if (priv->dad6_ip6_config) { + _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); + } else { + _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); + check_ip_state(self, FALSE, TRUE); + } + } } - /* Send ARP announcements */ + if (IS_IPv4) { + /* Send ARP announcements */ - if (nm_device_is_master(self)) { - CList * iter; - SlaveInfo *info; + if (nm_device_is_master(self)) { + CList * iter; + SlaveInfo *info; - /* Skip announcement if there are no device enslaved, for two reasons: - * 1) the master has a temporary MAC address until the first slave comes - * 2) announcements are going to be dropped anyway without slaves - */ - do_announce = FALSE; + /* Skip announcement if there are no device enslaved, for two reasons: + * 1) the master has a temporary MAC address until the first slave comes + * 2) announcements are going to be dropped anyway without slaves + */ + do_announce = FALSE; - c_list_for_each (iter, &priv->slaves) { - info = c_list_entry(iter, SlaveInfo, lst_slave); - if (info->slave_is_enslaved) { - do_announce = TRUE; - break; + c_list_for_each (iter, &priv->slaves) { + info = c_list_entry(iter, SlaveInfo, lst_slave); + if (info->slave_is_enslaved) { + do_announce = TRUE; + break; + } } - } - } else - do_announce = TRUE; + } else + do_announce = TRUE; - if (do_announce) - nm_device_arp_announce(self); + if (do_announce) + nm_device_arp_announce(self); + } - /* Enter the IP_CHECK state if this is the first method to complete */ - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); + if (IS_IPv4) { + /* Enter the IP_CHECK state if this is the first method to complete */ + _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_DONE); + check_ip_state(self, FALSE, TRUE); + } +} + +static void +activate_stage5_ip_config_result_4(NMDevice *self) +{ + activate_stage5_ip_config_result_x(self, AF_INET); } +static void +activate_stage5_ip_config_result_6(NMDevice *self) +{ + activate_stage5_ip_config_result_x(self, AF_INET6); +} + +#define activate_stage5_ip_config_result_x_fcn(addr_family) \ + (NM_IS_IPv4(addr_family) ? activate_stage5_ip_config_result_4 \ + : activate_stage5_ip_config_result_6) + void nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family, NMIPConfig *config) { NMDevicePrivate *priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); + 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 || (addr_family == AF_INET && nm_ip_config_get_addr_family(config) == AF_INET)); + g_return_if_fail(!config || (IS_IPv4 && nm_ip_config_get_addr_family(config) == AF_INET)); priv = NM_DEVICE_GET_PRIVATE(self); @@ -11913,13 +11989,15 @@ nm_device_activate_schedule_ip_config_result(NMDevice *self, int addr_family, NM _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_CONF); } - activation_source_schedule(self, activate_stage5_ip_config_result_x[IS_IPv4], addr_family); + activation_source_schedule(self, + activate_stage5_ip_config_result_x_fcn(addr_family), + addr_family); } NMDeviceIPState nm_device_activate_get_ip_state(NMDevice *self, int addr_family) { - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_val_if_fail(NM_IS_DEVICE(self), NM_DEVICE_IP_STATE_NONE); g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NM_DEVICE_IP_STATE_NONE); @@ -11994,89 +12072,6 @@ dad6_get_pending_addresses(NMDevice *self) return dad6_config; } -static void -activate_stage5_ip_config_result_6(NMDevice *self) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - NMActRequest * req; - const char * method; - int ip_ifindex; - int errsv; - - req = nm_device_get_act_request(self); - g_assert(req); - - /* Interface must be IFF_UP before IP config can be applied */ - ip_ifindex = nm_device_get_ip_ifindex(self); - g_return_if_fail(ip_ifindex); - - if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex) - && !nm_device_sys_iface_state_is_external_or_assume(self)) { - nm_platform_link_set_up(nm_device_get_platform(self), ip_ifindex, NULL); - if (!nm_platform_link_is_up(nm_device_get_platform(self), ip_ifindex)) - _LOGW(LOGD_DEVICE, - "interface %s not up for IP configuration", - nm_device_get_ip_iface(self)); - } - - if (ip_config_merge_and_apply(self, AF_INET6, TRUE)) { - if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE - && priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF) { - if (applied_config_get_current(&priv->dhcp6.ip6_config)) { - /* If IPv6 wasn't the first IP to complete, and DHCP was used, - * then ensure dispatcher scripts get the DHCP lease information. - */ - nm_dispatcher_call_device(NM_DISPATCHER_ACTION_DHCP6_CHANGE, - self, - NULL, - NULL, - NULL, - NULL); - } else { - /* still waiting for first dhcp6 lease. */ - return; - } - } - - /* Start IPv6 forwarding if we need it */ - method = nm_device_get_effective_ip_config_method(self, AF_INET6); - if (nm_streq(method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) { - if (!nm_platform_sysctl_set( - nm_device_get_platform(self), - NMP_SYSCTL_PATHID_ABSOLUTE("/proc/sys/net/ipv6/conf/all/forwarding"), - "1")) { - errsv = errno; - _LOGE(LOGD_SHARING, - "share: error enabling IPv6 forwarding: (%d) %s", - errsv, - nm_strerror_native(errsv)); - nm_device_ip_method_failed(self, - AF_INET6, - NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - } - } - - /* Check if we have to wait for DAD */ - if (priv->ip_state_6 == NM_DEVICE_IP_STATE_CONF && !priv->dad6_ip6_config) { - if (!priv->carrier && priv->ignore_carrier && get_ip_config_may_fail(self, AF_INET6)) - _LOGI(LOGD_DEVICE | LOGD_IP6, - "IPv6 DAD: carrier missing and ignored, not delaying activation"); - else - priv->dad6_ip6_config = dad6_get_pending_addresses(self); - - if (priv->dad6_ip6_config) { - _LOGD(LOGD_DEVICE | LOGD_IP6, "IPv6 DAD: awaiting termination"); - } else { - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_DONE); - check_ip_state(self, FALSE, TRUE); - } - } - } else { - _LOGW(LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); - nm_device_ip_method_failed(self, AF_INET6, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - } -} - /*****************************************************************************/ static void @@ -12230,7 +12225,7 @@ static void _cleanup_ip_pre(NMDevice *self, int addr_family, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_NONE); @@ -12326,55 +12321,86 @@ _nm_device_hash_check_invalid_keys(GHashTable * hash, } void -nm_device_reactivate_ip4_config(NMDevice * self, - NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new) +nm_device_reactivate_ip_config(NMDevice * self, + int addr_family, + NMSettingIPConfig *s_ip_old, + NMSettingIPConfig *s_ip_new) { + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDevicePrivate *priv; - const char * method_old, *method_new; + const char * method_old; + const char * method_new; g_return_if_fail(NM_IS_DEVICE(self)); + priv = NM_DEVICE_GET_PRIVATE(self); - if (priv->ip_state_4 != NM_DEVICE_IP_STATE_NONE) { - g_clear_object(&priv->con_ip_config_4); - g_clear_object(&priv->ext_ip_config_4); + 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); - g_clear_object(&priv->dev2_ip_config_4.current); - priv->con_ip_config_4 = nm_device_ip4_config_new(self); + } 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_ip4_new, + 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_ip4_old ? nm_setting_ip_config_get_method(s_ip4_old) - : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; - method_new = s_ip4_new ? nm_setting_ip_config_get_method(s_ip4_new) - : NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + 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); + method_new = (s_ip_new ? nm_setting_ip_config_get_method(s_ip_new) : NULL) + ?: (IS_IPv4 ? NM_SETTING_IP4_CONFIG_METHOD_DISABLED + : NM_SETTING_IP6_CONFIG_METHOD_IGNORE); - if (!nm_streq0(method_old, method_new)) { - _cleanup_ip_pre(self, AF_INET, CLEANUP_TYPE_DECONFIGURE); - _set_ip_state(self, AF_INET, NM_DEVICE_IP_STATE_WAIT); - if (!nm_device_activate_stage3_ip4_start(self)) - _LOGW(LOGD_IP4, "Failed to apply IPv4 configuration"); - return; + if (!nm_streq0(method_old, method_new)) { + _cleanup_ip_pre(self, addr_family, CLEANUP_TYPE_DECONFIGURE); + _set_ip_state(self, addr_family, NM_DEVICE_IP_STATE_WAIT); + if (!nm_device_activate_stage3_ip_start(self, addr_family)) { + _LOGW(LOGD_IP4, + "Failed to apply IPv%c configuration", + nm_utils_addr_family_to_char(addr_family)); } + return; + } - if (s_ip4_old && s_ip4_new) { - gint64 metric_old, metric_new; + 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_ip4_old); - metric_new = nm_setting_ip_config_get_route_metric(s_ip4_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 (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)); @@ -12387,60 +12413,7 @@ nm_device_reactivate_ip4_config(NMDevice * self, nm_dhcp_client_set_route_metric(priv->dhcp_data_4.client, nm_device_get_route_metric(self, AF_INET)); } - } - } - - if (nm_device_get_ip_ifindex(self) > 0 && !ip_config_merge_and_apply(self, AF_INET, TRUE)) - _LOGW(LOGD_IP4, "Failed to reapply IPv4 configuration"); - } -} - -void -nm_device_reactivate_ip6_config(NMDevice * self, - NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new) -{ - NMDevicePrivate *priv; - const char * method_old, *method_new; - - g_return_if_fail(NM_IS_DEVICE(self)); - priv = NM_DEVICE_GET_PRIVATE(self); - - if (priv->ip_state_6 != NM_DEVICE_IP_STATE_NONE) { - g_clear_object(&priv->con_ip_config_6); - g_clear_object(&priv->ext_ip_config_6); - g_clear_object(&priv->ac_ip6_config.current); - g_clear_object(&priv->dhcp6.ip6_config.current); - g_clear_object(&priv->dev2_ip_config_6.current); - if (priv->ipv6ll_handle && !IN6_IS_ADDR_UNSPECIFIED(&priv->ipv6ll_addr)) - priv->ipv6ll_has = TRUE; - priv->con_ip_config_6 = nm_device_ip6_config_new(self); - nm_ip6_config_merge_setting(priv->con_ip_config_6, - s_ip6_new, - nm_device_get_route_table(self, AF_INET6), - nm_device_get_route_metric(self, AF_INET6)); - - method_old = s_ip6_old ? nm_setting_ip_config_get_method(s_ip6_old) - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - method_new = s_ip6_new ? nm_setting_ip_config_get_method(s_ip6_new) - : NM_SETTING_IP6_CONFIG_METHOD_IGNORE; - - if (!nm_streq0(method_old, method_new)) { - _cleanup_ip_pre(self, AF_INET6, CLEANUP_TYPE_DECONFIGURE); - _set_ip_state(self, AF_INET6, NM_DEVICE_IP_STATE_WAIT); - if (!nm_device_activate_stage3_ip6_start(self)) - _LOGW(LOGD_IP6, "Failed to apply IPv6 configuration"); - return; - } - - if (s_ip6_old && s_ip6_new) { - gint64 metric_old, metric_new; - - /* See comment in nm_device_reactivate_ip4_config() */ - metric_old = nm_setting_ip_config_get_route_metric(s_ip6_old); - metric_new = nm_setting_ip_config_get_route_metric(s_ip6_new); - - if (metric_old != metric_new) { + } 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)); @@ -12459,9 +12432,12 @@ nm_device_reactivate_ip6_config(NMDevice * self, } } } + } - if (nm_device_get_ip_ifindex(self) > 0 && !ip_config_merge_and_apply(self, AF_INET6, TRUE)) - _LOGW(LOGD_IP4, "Failed to reapply IPv6 configuration"); + 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)); } } @@ -12518,28 +12494,41 @@ can_reapply_change(NMDevice * self, NM_SETTING_CONNECTION_LLDP, NM_SETTING_CONNECTION_MDNS, NM_SETTING_CONNECTION_LLMNR); - } else if (NM_IN_STRSET(setting_name, - NM_SETTING_USER_SETTING_NAME, - NM_SETTING_PROXY_SETTING_NAME, - NM_SETTING_IP4_CONFIG_SETTING_NAME, - NM_SETTING_IP6_CONFIG_SETTING_NAME)) { + } + + if (NM_IN_STRSET(setting_name, + NM_SETTING_USER_SETTING_NAME, + NM_SETTING_PROXY_SETTING_NAME, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME)) + return TRUE; + + if (nm_streq(setting_name, NM_SETTING_WIRED_SETTING_NAME)) { + if (NM_IN_SET(NM_DEVICE_GET_CLASS(self)->get_configured_mtu, + nm_device_get_configured_mtu_wired_parent, + nm_device_get_configured_mtu_for_wired)) { + return nm_device_hash_check_invalid_keys(diffs, + NM_SETTING_WIRED_SETTING_NAME, + error, + NM_SETTING_WIRED_MTU); + } + goto out_fail; + } + + if (nm_streq(setting_name, NM_SETTING_OVS_EXTERNAL_IDS_SETTING_NAME) + && NM_DEVICE_GET_CLASS(self)->can_reapply_change_ovs_external_ids) { + /* TODO: this means, you cannot reapply changes to the external-ids for + * OVS system interfaces. */ return TRUE; - } else if (nm_streq(setting_name, NM_SETTING_WIRED_SETTING_NAME) - && NM_IN_SET(NM_DEVICE_GET_CLASS(self)->get_configured_mtu, - nm_device_get_configured_mtu_wired_parent, - nm_device_get_configured_mtu_for_wired)) { - return nm_device_hash_check_invalid_keys(diffs, - NM_SETTING_WIRED_SETTING_NAME, - error, - NM_SETTING_WIRED_MTU); - } else { - g_set_error(error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, - "Can't reapply any changes to '%s' setting", - setting_name); - return FALSE; } + +out_fail: + g_set_error(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Can't reapply any changes to '%s' setting", + setting_name); + return FALSE; } static void @@ -12682,6 +12671,8 @@ check_and_reapply_connection(NMDevice * self, con_old = applied_clone = nm_simple_connection_new_clone(applied); con_new = applied; + /* FIXME(applied-connection-immutable): we should not modify the applied + * connection but replace it with a new (immutable) instance. */ nm_connection_replace_settings_from_connection(applied, connection_clean); nm_connection_clear_secrets(applied); } else @@ -12716,8 +12707,8 @@ check_and_reapply_connection(NMDevice * self, /* Allow reapply of MTU */ priv->mtu_source = NM_DEVICE_MTU_SOURCE_NONE; - nm_device_reactivate_ip4_config(self, s_ip4_old, s_ip4_new); - nm_device_reactivate_ip6_config(self, s_ip6_old, s_ip6_new); + nm_device_reactivate_ip_config(self, AF_INET, s_ip4_old, s_ip4_new); + nm_device_reactivate_ip_config(self, AF_INET6, s_ip6_old, s_ip6_new); _routing_rules_sync(self, NM_TERNARY_TRUE); @@ -13328,6 +13319,12 @@ nm_device_disconnect_active_connection(NMActiveConnection * active, if (NM_ACTIVE_CONNECTION(priv->act_request.obj) == active) { if (priv->state < NM_DEVICE_STATE_DEACTIVATING) { + /* When the user actively deactivates a profile, we set + * the sys-iface-state to managed so that we deconfigure/cleanup the interface. + * But for external connections that go down otherwise, we don't want to touch the interface. */ + if (nm_device_sys_iface_state_is_external(self)) + nm_device_sys_iface_state_set(self, NM_DEVICE_SYS_IFACE_STATE_MANAGED); + nm_device_state_changed(self, NM_DEVICE_STATE_DEACTIVATING, device_reason); } else { /* @active is the current ac of @self, but it's going down already. @@ -13457,7 +13454,7 @@ nm_device_set_proxy_config(NMDevice *self, const char *pac_url) NMDhcpConfig * nm_device_get_dhcp_config(NMDevice *self, int addr_family) { - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_val_if_fail(NM_IS_DEVICE(self), NULL); @@ -13482,7 +13479,7 @@ nm_device_set_ip_config(NMDevice * self, GPtrArray * ip4_dev_route_blacklist) { NMDevicePrivate * priv = NM_DEVICE_GET_PRIVATE(self); - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMIPConfig * old_config; gboolean has_changes = FALSE; gboolean success = TRUE; @@ -13498,7 +13495,7 @@ nm_device_set_ip_config(NMDevice * self, }))); nm_assert(IS_IPv4 || !ip4_dev_route_blacklist); - _LOGD(LOGD_IP_from_af(addr_family), + _LOGD(LOGD_IPX(IS_IPv4), "ip%c-config: update (commit=%d, new-config=%p)", nm_utils_addr_family_to_char(addr_family), commit, @@ -13535,7 +13532,7 @@ nm_device_set_ip_config(NMDevice * self, * 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_IP_from_af(addr_family), + _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))); @@ -13546,14 +13543,14 @@ nm_device_set_ip_config(NMDevice * self, if (!nm_dbus_object_is_exported(NM_DBUS_OBJECT(new_config))) nm_dbus_object_export(NM_DBUS_OBJECT(new_config)); - _LOGD(LOGD_IP_from_af(addr_family), + _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_IP_from_af(addr_family), + _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))); @@ -13671,7 +13668,7 @@ void nm_device_set_dev2_ip_config(NMDevice *self, int addr_family, NMIPConfig *config) { NMDevicePrivate *priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); + 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)); @@ -14221,7 +14218,7 @@ update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs is_up = nm_platform_link_is_up(nm_device_get_platform(self), ifindex); - if (addr_family == AF_INET) { + 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), @@ -14270,7 +14267,7 @@ update_ext_ip_config(NMDevice *self, int addr_family, gboolean intersect_configs } } else { - nm_assert(addr_family == AF_INET6); + nm_assert(!NM_IS_IPv4(addr_family)); g_clear_object(&priv->ext_ip_config_6); g_clear_object(&priv->ext_ip6_config_captured); @@ -14345,13 +14342,13 @@ update_ip_config(NMDevice *self, int addr_family) nm_assert_addr_family(addr_family); - if (addr_family == AF_INET) + 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 (addr_family == AF_INET) { + if (NM_IS_IPv4(addr_family)) { if (priv->ext_ip_config_4) ip_config_merge_and_apply(self, AF_INET, FALSE); } else { @@ -14376,7 +14373,7 @@ static gboolean queued_ip_config_change(NMDevice *self, int addr_family) { NMDevicePrivate *priv; - const gboolean IS_IPv4 = (addr_family == AF_INET); + const int IS_IPv4 = NM_IS_IPv4(addr_family); g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); @@ -14391,7 +14388,8 @@ queued_ip_config_change(NMDevice *self, int addr_family) * 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[IS_IPv4]) + && 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; @@ -15414,6 +15412,15 @@ check_connection_available(NMDevice * self, if (nm_device_is_master(self)) return TRUE; + if (!priv->up) { + /* If the device is !IFF_UP it also has no carrier. But we assume that if we + * would start activating the device (and thereby set the device IFF_UP), + * that we would get a carrier. We only know after we set the device up, + * and we only set it up after we start activating it. So presumably, this + * profile would be available (but we just don't know). */ + return TRUE; + } + nm_utils_error_set_literal(error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, "device has no carrier"); @@ -15729,6 +15736,7 @@ _cancel_activation(NMDevice *self) priv->fw_state = FIREWALL_STATE_INITIALIZED; } + dispatcher_cleanup(self); ip_check_gw_ping_cleanup(self); /* Break the activation chain */ @@ -15740,6 +15748,7 @@ static void _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + guint i; _cancel_activation(self); @@ -15764,6 +15773,9 @@ _cleanup_generic_pre(NMDevice *self, CleanupType cleanup_type) nm_clear_pointer(&priv->shared_ip_handle, nm_netns_shared_ip_release); + for (i = 0; i < 2; i++) + nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free); + _cleanup_ip_pre(self, AF_INET, cleanup_type); _cleanup_ip_pre(self, AF_INET6, cleanup_type); } @@ -16431,9 +16443,9 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_device_hw_addr_reset(self, "unmanage"); set_nm_ipv6ll(self, FALSE); restore_ip6_properties(self); - break; } } + nm_device_sys_iface_state_set(self, NM_DEVICE_SYS_IFACE_STATE_EXTERNAL); break; case NM_DEVICE_STATE_UNAVAILABLE: if (old_state == NM_DEVICE_STATE_UNMANAGED) { @@ -16559,7 +16571,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, priv->sriov_reset_pending++; sriov_op_queue(self, 0, - NM_TERNARY_TRUE, + NM_OPTION_BOOL_TRUE, sriov_reset_on_deactivate_cb, nm_utils_user_data_pack(self, GINT_TO_POINTER(reason))); } @@ -16611,7 +16623,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, if (priv->ifindex > 0 && (s_sriov = nm_device_get_applied_setting(self, NM_TYPE_SETTING_SRIOV))) { priv->sriov_reset_pending++; - sriov_op_queue(self, 0, NM_TERNARY_TRUE, sriov_reset_on_failure_cb, self); + sriov_op_queue(self, 0, NM_OPTION_BOOL_TRUE, sriov_reset_on_failure_cb, self); break; } /* Schedule the transition to DISCONNECTED. The device can't transition @@ -16621,8 +16633,22 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, nm_device_queue_state(self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); break; case NM_DEVICE_STATE_IP_CHECK: - if (priv->fw_state >= FIREWALL_STATE_INITIALIZED && priv->ip_iface - && !nm_device_sys_iface_state_is_external(self)) { + { + gboolean change_zone = FALSE; + + if (!nm_device_sys_iface_state_is_external(self)) { + if (priv->ip_iface) { + /* The device now has a @ip_iface different from the + * @iface on which we previously set the zone. */ + change_zone = TRUE; + } else if (priv->fw_state == FIREWALL_STATE_UNMANAGED && priv->ifindex > 0) { + /* We didn't set the zone earlier because there was + * no ifindex. */ + change_zone = TRUE; + } + } + + if (change_zone) { priv->fw_state = FIREWALL_STATE_WAIT_IP_CONFIG; fw_change_zone(self); } else @@ -16633,6 +16659,7 @@ _set_state_full(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, */ notify_ip_properties(self); break; + } case NM_DEVICE_STATE_SECONDARIES: ip_check_gw_ping_cleanup(self); _LOGD(LOGD_DEVICE, "device entered SECONDARIES state"); @@ -17418,7 +17445,10 @@ nm_device_get_permanent_hw_address_full(NMDevice *self, { NMDevicePrivate *priv; - g_return_val_if_fail(NM_IS_DEVICE(self), NULL); + g_return_val_if_fail(NM_IS_DEVICE(self), ({ + NM_SET_OUT(out_is_fake, FALSE); + NULL; + })); priv = NM_DEVICE_GET_PRIVATE(self); @@ -17589,6 +17619,209 @@ nm_device_auth_retries_try_next(NMDevice *self) return TRUE; } +static void +hostname_dns_lookup_callback(GObject *source, GAsyncResult *result, gpointer user_data) +{ + HostnameResolver *resolver; + NMDevice * self; + gs_free char * hostname = NULL; + gs_free char * addr_str = NULL; + gs_free_error GError *error = NULL; + + hostname = g_resolver_lookup_by_address_finish(G_RESOLVER(source), result, &error); + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + resolver = user_data; + self = resolver->device; + resolver->state = RESOLVER_DONE; + resolver->hostname = g_strdup(hostname); + + _LOGD(LOGD_DNS, + "hostname-from-dns: lookup done for %s, result %s%s%s", + (addr_str = g_inet_address_to_string(resolver->address)), + NM_PRINT_FMT_QUOTE_STRING(hostname)); + + nm_clear_g_cancellable(&resolver->cancellable); + g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0); +} + +static gboolean +hostname_dns_address_timeout(gpointer user_data) +{ + HostnameResolver *resolver = user_data; + NMDevice * self = resolver->device; + + g_return_val_if_fail(NM_IS_DEVICE(self), G_SOURCE_REMOVE); + + nm_assert(resolver->state == RESOLVER_WAIT_ADDRESS); + nm_assert(!resolver->address); + nm_assert(!resolver->cancellable); + + _LOGT(LOGD_DNS, + "hostname-from-dns: timed out while waiting IPv%c address", + nm_utils_addr_family_to_char(resolver->addr_family)); + + resolver->timeout_id = 0; + resolver->state = RESOLVER_DONE; + g_signal_emit(self, signals[DNS_LOOKUP_DONE], 0); + + return G_SOURCE_REMOVE; +} + +static const char * +_resolver_state_to_string(ResolverState state) +{ + switch (state) { + case RESOLVER_WAIT_ADDRESS: + return "wait-address"; + case RESOLVER_IN_PROGRESS: + return "in-progress"; + case RESOLVER_DONE: + return "done"; + default: + nm_assert_not_reached(); + return "unknown"; + } +} + +void +nm_device_clear_dns_lookup_data(NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE(self); + guint i; + + for (i = 0; i < 2; i++) + nm_clear_pointer(&priv->hostname_resolver_x[i], _hostname_resolver_free); +} + +/* return value is valid only immediately */ +const char * +nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_wait) +{ + NMDevicePrivate * priv; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + HostnameResolver *resolver; + NMIPConfig * ip_config; + const char * method; + gboolean address_changed = FALSE; + gs_unref_object GInetAddress *new_address = NULL; + + g_return_val_if_fail(NM_IS_DEVICE(self), NULL); + priv = NM_DEVICE_GET_PRIVATE(self); + + /* If the device is not supposed to have addresses, + * return an immediate empty result.*/ + if (!nm_device_get_applied_connection(self)) { + NM_SET_OUT(out_wait, FALSE); + return NULL; + } + + method = nm_device_get_effective_ip_config_method(self, addr_family); + if (IS_IPv4) { + if (NM_IN_STRSET(method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) { + nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); + NM_SET_OUT(out_wait, FALSE); + return NULL; + } + } else { + if (NM_IN_STRSET(method, + NM_SETTING_IP6_CONFIG_METHOD_DISABLED, + NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) { + nm_clear_pointer(&priv->hostname_resolver_x[IS_IPv4], _hostname_resolver_free); + NM_SET_OUT(out_wait, FALSE); + return NULL; + } + } + + resolver = priv->hostname_resolver_x[IS_IPv4]; + if (!resolver) { + resolver = g_slice_new(HostnameResolver); + *resolver = (HostnameResolver){ + .resolver = g_resolver_get_default(), + .device = self, + .addr_family = addr_family, + .state = RESOLVER_WAIT_ADDRESS, + }; + priv->hostname_resolver_x[IS_IPv4] = resolver; + } + + /* Determine the first address of the interface and + * whether it changed from the previous lookup */ + ip_config = priv->ip_config_x[IS_IPv4]; + if (ip_config) { + const NMPlatformIPAddress *addr; + + addr = nm_ip_config_get_first_address(ip_config); + if (addr) { + new_address = g_inet_address_new_from_bytes(addr->address_ptr, + IS_IPv4 ? G_SOCKET_FAMILY_IPV4 + : G_SOCKET_FAMILY_IPV6); + } + } + + if (new_address && resolver->address) { + if (!g_inet_address_equal(new_address, resolver->address)) + address_changed = TRUE; + } else if (new_address != resolver->address) + address_changed = TRUE; + + { + gs_free char *old_str = NULL; + gs_free char *new_str = NULL; + + _LOGT(LOGD_DNS, + "hostname-from-dns: ipv%c resolver state %s, old address %s, new address %s", + nm_utils_addr_family_to_char(resolver->addr_family), + _resolver_state_to_string(resolver->state), + resolver->address ? (old_str = g_inet_address_to_string(resolver->address)) + : "(null)", + new_address ? (new_str = g_inet_address_to_string(new_address)) : "(null)"); + } + + /* In every state, if the address changed, we restart + * the resolution with the new address */ + if (address_changed) { + nm_clear_g_cancellable(&resolver->cancellable); + g_clear_object(&resolver->address); + resolver->state = RESOLVER_WAIT_ADDRESS; + } + + if (address_changed && new_address) { + gs_free char *str = NULL; + + _LOGT(LOGD_DNS, + "hostname-from-dns: starting lookup for address %s", + (str = g_inet_address_to_string(new_address))); + + resolver->state = RESOLVER_IN_PROGRESS; + resolver->cancellable = g_cancellable_new(); + resolver->address = g_steal_pointer(&new_address); + g_resolver_lookup_by_address_async(resolver->resolver, + resolver->address, + resolver->cancellable, + hostname_dns_lookup_callback, + resolver); + nm_clear_g_source(&resolver->timeout_id); + } + + switch (resolver->state) { + case RESOLVER_WAIT_ADDRESS: + if (!resolver->timeout_id) + resolver->timeout_id = g_timeout_add(30000, hostname_dns_address_timeout, resolver); + NM_SET_OUT(out_wait, TRUE); + return NULL; + case RESOLVER_IN_PROGRESS: + NM_SET_OUT(out_wait, TRUE); + return NULL; + case RESOLVER_DONE: + NM_SET_OUT(out_wait, FALSE); + return resolver->hostname; + } + + return nm_assert_unreachable_val(NULL); +} + /*****************************************************************************/ static const char * @@ -18084,6 +18317,7 @@ dispose(GObject *object) 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); @@ -18766,6 +19000,16 @@ nm_device_class_init(NMDeviceClass *klass) NULL, G_TYPE_NONE, 0); + + signals[DNS_LOOKUP_DONE] = g_signal_new(NM_DEVICE_DNS_LOOKUP_DONE, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); } /* Connection defaults from plugins */ diff --git a/src/devices/nm-device.h b/src/core/devices/nm-device.h index 3eae9318..72777d0a 100644 --- a/src/devices/nm-device.h +++ b/src/core/devices/nm-device.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -116,6 +116,7 @@ nm_device_state_reason_check(NMDeviceStateReason reason) #define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */ /* 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_IP6_PREFIX_DELEGATED "ip6-prefix-delegated" @@ -243,6 +244,16 @@ typedef struct _NMDeviceClass { */ bool mtu_force_set : 1; + /* Control whether to call stage1 and stage2 callbacks also for assuming + * a device or for external activations. In this case, the callback must + * take care not to touch the device's configuration. */ + bool act_stage1_prepare_also_for_external_or_assume : 1; + bool act_stage2_config_also_for_external_or_assume : 1; + + bool act_stage1_prepare_set_hwaddr_ethernet : 1; + + bool can_reapply_change_ovs_external_ids : 1; + void (*state_changed)(NMDevice * device, NMDeviceState new_state, NMDeviceState old_state, @@ -448,14 +459,6 @@ typedef struct _NMDeviceClass { gboolean (*set_platform_mtu)(NMDevice *self, guint32 mtu); - /* Control whether to call stage1 and stage2 callbacks also for assuming - * a device or for external activations. In this case, the callback must - * take care not to touch the device's configuration. */ - bool act_stage1_prepare_also_for_external_or_assume : 1; - bool act_stage2_config_also_for_external_or_assume : 1; - - bool act_stage1_prepare_set_hwaddr_ethernet : 1; - } NMDeviceClass; GType nm_device_get_type(void); @@ -800,12 +803,10 @@ void nm_device_reapply_settings_immediately(NMDevice *self); void nm_device_update_firewall_zone(NMDevice *self); void nm_device_update_metered(NMDevice *self); -void nm_device_reactivate_ip4_config(NMDevice * device, - NMSettingIPConfig *s_ip4_old, - NMSettingIPConfig *s_ip4_new); -void nm_device_reactivate_ip6_config(NMDevice * device, - NMSettingIPConfig *s_ip6_old, - NMSettingIPConfig *s_ip6_new); +void nm_device_reactivate_ip_config(NMDevice * device, + int addr_family, + NMSettingIPConfig *s_ip_old, + NMSettingIPConfig *s_ip_new); gboolean nm_device_update_hw_address(NMDevice *self); void nm_device_update_initial_hw_address(NMDevice *self); @@ -865,4 +866,9 @@ const char *nm_device_state_reason_to_str(NMDeviceStateReason reason); gboolean nm_device_is_vpn(NMDevice *self); +const char * +nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_pending); + +void nm_device_clear_dns_lookup_data(NMDevice *self); + #endif /* __NETWORKMANAGER_DEVICE_H__ */ diff --git a/src/devices/nm-lldp-listener.c b/src/core/devices/nm-lldp-listener.c index 25d863c8..c60fb3ad 100644 --- a/src/devices/nm-lldp-listener.c +++ b/src/core/devices/nm-lldp-listener.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-lldp-listener.h" @@ -103,8 +103,8 @@ typedef struct { static void lldp_neighbor_get_raw(LldpNeighbor *neigh, const guint8 **out_raw_data, gsize *out_raw_len) { - gconstpointer raw_data; - gsize raw_len; + gconstpointer raw_data = NULL; + gsize raw_len = 0; int r; nm_assert(neigh); @@ -1075,7 +1075,7 @@ nm_lldp_listener_init(NMLldpListener *self) NMLldpListener * nm_lldp_listener_new(void) { - return (NMLldpListener *) g_object_new(NM_TYPE_LLDP_LISTENER, NULL); + return g_object_new(NM_TYPE_LLDP_LISTENER, NULL); } static void diff --git a/src/devices/nm-lldp-listener.h b/src/core/devices/nm-lldp-listener.h index 8c83cd67..9d3e2436 100644 --- a/src/devices/nm-lldp-listener.h +++ b/src/core/devices/nm-lldp-listener.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/core/devices/ovs/meson.build b/src/core/devices/ovs/meson.build new file mode 100644 index 00000000..81c29bd6 --- /dev/null +++ b/src/core/devices/ovs/meson.build @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnm_device_plugin_ovs = shared_module( + 'nm-device-plugin-ovs', + sources: files( + 'nm-device-ovs-bridge.c', + 'nm-device-ovs-interface.c', + 'nm-device-ovs-port.c', + 'nm-ovsdb.c', + 'nm-ovs-factory.c', + ), + dependencies: [ + core_plugin_dep, + jansson_dep, + ], + c_args: daemon_c_flags, + link_args: ldflags_linker_script_devices, + link_depends: linker_script_devices, + install: true, + install_dir: nm_plugindir, +) + +core_plugins += libnm_device_plugin_ovs + +test( + 'check-local-devices-ovs', + check_exports, + args: [ + libnm_device_plugin_ovs.full_path(), + linker_script_devices, + ], +) diff --git a/src/devices/ovs/nm-device-ovs-bridge.c b/src/core/devices/ovs/nm-device-ovs-bridge.c index a7b7a539..3ae8a481 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.c +++ b/src/core/devices/ovs/nm-device-ovs-bridge.c @@ -1,11 +1,13 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ovs-bridge.h" + +#include "nm-device-ovs-interface.h" #include "nm-device-ovs-port.h" #include "nm-ovsdb.h" @@ -13,9 +15,11 @@ #include "nm-active-connection.h" #include "nm-setting-connection.h" #include "nm-setting-ovs-bridge.h" +#include "nm-setting-ovs-external-ids.h" +#include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceOvsBridge #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceOvsBridge); /*****************************************************************************/ @@ -87,6 +91,39 @@ static void release_slave(NMDevice *device, NMDevice *slave, gboolean configure) {} +void +nm_device_ovs_reapply_connection(NMDevice *self, NMConnection *con_old, NMConnection *con_new) +{ + NMDeviceType device_type; + GType type; + + nm_assert(NM_IS_DEVICE(self)); + nm_assert(g_type_parent(G_TYPE_FROM_INSTANCE(self)) == NM_TYPE_DEVICE); + + /* NMDevice's reapply_connection() doesn't do anything. No need to call the parent + * implementation. */ + + _LOGD(LOGD_DEVICE, "reapplying settings for OVS device"); + + type = G_OBJECT_TYPE(self); + if (type == NM_TYPE_DEVICE_OVS_INTERFACE) + device_type = NM_DEVICE_TYPE_OVS_INTERFACE; + else if (type == NM_TYPE_DEVICE_OVS_PORT) + device_type = NM_DEVICE_TYPE_OVS_PORT; + else { + nm_assert(type == NM_TYPE_DEVICE_OVS_BRIDGE); + device_type = NM_DEVICE_TYPE_OVS_BRIDGE; + } + + nm_ovsdb_set_external_ids( + nm_ovsdb_get(), + device_type, + nm_device_get_ip_iface(self), + nm_connection_get_uuid(con_new), + _nm_connection_get_setting(con_old, NM_TYPE_SETTING_OVS_EXTERNAL_IDS), + _nm_connection_get_setting(con_new, NM_TYPE_SETTING_OVS_EXTERNAL_IDS)); +} + /*****************************************************************************/ static void @@ -114,12 +151,14 @@ nm_device_ovs_bridge_class_init(NMDeviceOvsBridgeClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_BRIDGE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_master = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->unrealize = unrealize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->is_master = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->unrealize = unrealize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->enslave_slave = enslave_slave; + device_class->release_slave = release_slave; + device_class->can_reapply_change_ovs_external_ids = TRUE; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/devices/ovs/nm-device-ovs-bridge.h b/src/core/devices/ovs/nm-device-ovs-bridge.h index ba04bfeb..2b893343 100644 --- a/src/devices/ovs/nm-device-ovs-bridge.h +++ b/src/core/devices/ovs/nm-device-ovs-bridge.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -22,4 +22,9 @@ typedef struct _NMDeviceOvsBridgeClass NMDeviceOvsBridgeClass; GType nm_device_ovs_bridge_get_type(void); +/*****************************************************************************/ + +void +nm_device_ovs_reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_new); + #endif /* __NETWORKMANAGER_DEVICE_OVS_BRIDGE_H__ */ diff --git a/src/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 16b6e04d..5d07c211 100644 --- a/src/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -1,11 +1,13 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ovs-interface.h" + +#include "nm-device-ovs-bridge.h" #include "nm-ovsdb.h" #include "devices/nm-device-private.h" @@ -14,13 +16,14 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" +#define _NMLOG_DEVICE_TYPE NMDeviceOvsInterface #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceOvsInterface); /*****************************************************************************/ typedef struct { - bool waiting_for_interface : 1; + NMOvsdb *ovsdb; + bool waiting_for_interface : 1; } NMDeviceOvsInterfacePrivate; struct _NMDeviceOvsInterface { @@ -68,7 +71,10 @@ get_generic_capabilities(NMDevice *device) static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { - return TRUE; + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + return nm_ovsdb_is_ready(priv->ovsdb); } static gboolean @@ -150,6 +156,9 @@ set_platform_mtu_cb(GError *error, gpointer user_data) static gboolean set_platform_mtu(NMDevice *device, guint32 mtu) { + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + /* * If the MTU is not set in ovsdb, Open vSwitch will change * the MTU of an internal interface to match the minimum of @@ -160,7 +169,7 @@ set_platform_mtu(NMDevice *device, guint32 mtu) * it can be stopped during shutdown. */ if (_is_internal_interface(device)) { - nm_ovsdb_set_interface_mtu(nm_ovsdb_get(), + nm_ovsdb_set_interface_mtu(priv->ovsdb, nm_device_get_ip_iface(device), mtu, set_platform_mtu_cb, @@ -359,8 +368,41 @@ can_update_from_platform_link(NMDevice *device, const NMPlatformLink *plink) /*****************************************************************************/ static void +ovsdb_ready(NMOvsdb *ovsdb, NMDeviceOvsInterface *self) +{ + NMDevice *device = NM_DEVICE(self); + + nm_device_queue_recheck_available(device, + NM_DEVICE_STATE_REASON_NONE, + NM_DEVICE_STATE_REASON_NONE); + nm_device_recheck_available_connections(device); + nm_device_emit_recheck_auto_activate(device); +} + +static void nm_device_ovs_interface_init(NMDeviceOvsInterface *self) -{} +{ + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + priv->ovsdb = g_object_ref(nm_ovsdb_get()); + + if (!nm_ovsdb_is_ready(priv->ovsdb)) + g_signal_connect(priv->ovsdb, NM_OVSDB_READY, G_CALLBACK(ovsdb_ready), self); +} + +static void +dispose(GObject *object) +{ + NMDeviceOvsInterface * self = NM_DEVICE_OVS_INTERFACE(object); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + if (priv->ovsdb) { + g_signal_handlers_disconnect_by_func(priv->ovsdb, G_CALLBACK(ovsdb_ready), self); + g_clear_object(&priv->ovsdb); + } + + G_OBJECT_CLASS(nm_device_ovs_interface_parent_class)->dispose(object); +} static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT( @@ -372,9 +414,12 @@ static const NMDBusInterfaceInfoExtended interface_info_device_ovs_interface = { static void nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) { + GObjectClass * object_class = G_OBJECT_CLASS(klass); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(klass); NMDeviceClass * device_class = NM_DEVICE_CLASS(klass); + object_class->dispose = dispose; + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS(&interface_info_device_ovs_interface); @@ -382,17 +427,19 @@ nm_device_ovs_interface_class_init(NMDeviceOvsInterfaceClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_INTERFACE_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(NM_LINK_TYPE_OPENVSWITCH); - device_class->can_update_from_platform_link = can_update_from_platform_link; - device_class->deactivate = deactivate; - device_class->deactivate_async = deactivate_async; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->is_available = is_available; - device_class->check_connection_compatible = check_connection_compatible; - device_class->link_changed = link_changed; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->can_unmanaged_external_down = can_unmanaged_external_down; - device_class->set_platform_mtu = set_platform_mtu; - device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->can_update_from_platform_link = can_update_from_platform_link; + device_class->deactivate = deactivate; + device_class->deactivate_async = deactivate_async; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->link_changed = link_changed; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->can_unmanaged_external_down = can_unmanaged_external_down; + device_class->set_platform_mtu = set_platform_mtu; + device_class->get_configured_mtu = nm_device_get_configured_mtu_for_wired; + device_class->can_reapply_change_ovs_external_ids = TRUE; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/devices/ovs/nm-device-ovs-interface.h b/src/core/devices/ovs/nm-device-ovs-interface.h index 902847de..03b0e9a4 100644 --- a/src/devices/ovs/nm-device-ovs-interface.h +++ b/src/core/devices/ovs/nm-device-ovs-interface.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/ovs/nm-device-ovs-port.c b/src/core/devices/ovs/nm-device-ovs-port.c index de98e29e..2ecb95e8 100644 --- a/src/devices/ovs/nm-device-ovs-port.c +++ b/src/core/devices/ovs/nm-device-ovs-port.c @@ -1,12 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-ovs-port.h" + #include "nm-device-ovs-interface.h" +#include "nm-device-ovs-bridge.h" #include "nm-ovsdb.h" #include "devices/nm-device-private.h" @@ -15,8 +17,8 @@ #include "nm-setting-ovs-port.h" #include "nm-setting-ovs-port.h" +#define _NMLOG_DEVICE_TYPE NMDeviceOvsPort #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceOvsPort); /*****************************************************************************/ @@ -182,11 +184,13 @@ nm_device_ovs_port_class_init(NMDeviceOvsPortClass *klass) device_class->connection_type_check_compatible = NM_SETTING_OVS_PORT_SETTING_NAME; device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES(); - device_class->is_master = TRUE; - device_class->get_type_description = get_type_description; - device_class->create_and_realize = create_and_realize; - device_class->get_generic_capabilities = get_generic_capabilities; - device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; - device_class->enslave_slave = enslave_slave; - device_class->release_slave = release_slave; + device_class->is_master = TRUE; + device_class->get_type_description = get_type_description; + device_class->create_and_realize = create_and_realize; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->act_stage3_ip_config_start = act_stage3_ip_config_start; + device_class->enslave_slave = enslave_slave; + device_class->release_slave = release_slave; + device_class->can_reapply_change_ovs_external_ids = TRUE; + device_class->reapply_connection = nm_device_ovs_reapply_connection; } diff --git a/src/devices/ovs/nm-device-ovs-port.h b/src/core/devices/ovs/nm-device-ovs-port.h index 3f5d7793..f4516c01 100644 --- a/src/devices/ovs/nm-device-ovs-port.h +++ b/src/core/devices/ovs/nm-device-ovs-port.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/devices/ovs/nm-ovs-factory.c b/src/core/devices/ovs/nm-ovs-factory.c index e1feacbd..e7af38d8 100644 --- a/src/devices/ovs/nm-ovs-factory.c +++ b/src/core/devices/ovs/nm-ovs-factory.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-manager.h" #include "nm-ovsdb.h" @@ -64,7 +64,7 @@ G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { nm_manager_set_capability(NM_MANAGER_GET, NM_CAPABILITY_OVS); - return (NMDeviceFactory *) g_object_new(NM_TYPE_OVS_FACTORY, NULL); + return g_object_new(NM_TYPE_OVS_FACTORY, NULL); } static NMDevice * @@ -108,10 +108,21 @@ new_device_from_type(const char *name, NMDeviceType device_type) static void ovsdb_device_added(NMOvsdb * ovsdb, const char * name, - NMDeviceType device_type, + guint device_type_i, + const char * subtype, NMDeviceFactory *self) { - NMDevice *device = NULL; + const NMDeviceType device_type = device_type_i; + NMDevice * device; + + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE + && !NM_IN_STRSET(subtype, "internal", "patch")) { + /* system interfaces refer to kernel devices and + * don't need to be created by this factory. Ignore + * anything that is not an internal or patch + * interface. */ + return; + } device = new_device_from_type(name, device_type); if (!device) @@ -124,23 +135,67 @@ ovsdb_device_added(NMOvsdb * ovsdb, static void ovsdb_device_removed(NMOvsdb * ovsdb, const char * name, - NMDeviceType device_type, + guint device_type_i, + const char * subtype, NMDeviceFactory *self) { - NMDevice * device; - NMDeviceState device_state; + const NMDeviceType device_type = device_type_i; + NMDevice * device = NULL; + NMDeviceState device_state; + gboolean is_system_interface = FALSE; + + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE + && !NM_IN_STRSET(subtype, "internal", "patch", "system")) + return; + + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && nm_streq0(subtype, "system")) { + NMDevice * d; + const CList * list; + NMSettingOvsInterface *s_ovs_int; + + /* The device associated to an OVS system interface can be of + * any kind. Find an interface with the same name and which has + * the OVS-interface setting. */ + is_system_interface = TRUE; + nm_manager_for_each_device (NM_MANAGER_GET, d, list) { + if (!nm_streq0(nm_device_get_iface(d), name)) + continue; + s_ovs_int = nm_device_get_applied_setting(d, NM_TYPE_SETTING_OVS_INTERFACE); + if (!s_ovs_int) + continue; + if (!nm_streq0(nm_setting_ovs_interface_get_interface_type(s_ovs_int), "system")) + continue; + /* Failing the system interface device is almost always the right + * thing to do when the ovsdb entry is removed. However, to avoid + * that a late device-removed signal tears down a different, + * newly-activated connection, let's also check that we have a master. + * Or in alternative, that the device is assumed/external: in such + * case it's always fine to fail the device. + */ + if (!nm_device_get_master(d) && !nm_device_sys_iface_state_is_external_or_assume(d)) + continue; + + device = d; + } + } else { + device = nm_manager_get_device(NM_MANAGER_GET, name, device_type); + } - device = nm_manager_get_device(NM_MANAGER_GET, name, device_type); if (!device) return; device_state = nm_device_get_state(device); - if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && device_state > NM_DEVICE_STATE_DISCONNECTED + + if (device_type == NM_DEVICE_TYPE_OVS_INTERFACE && nm_device_get_act_request(device) && device_state < NM_DEVICE_STATE_DEACTIVATING) { nm_device_state_changed(device, NM_DEVICE_STATE_DEACTIVATING, - NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED); - } else if (device_state == NM_DEVICE_STATE_UNMANAGED) { + NM_DEVICE_STATE_REASON_REMOVED); + return; + } + + /* OVS system interfaces still exist even without the ovsdb entry */ + if (!is_system_interface && device_state == NM_DEVICE_STATE_UNMANAGED) { nm_device_unrealize(device, TRUE, NULL); } } diff --git a/src/devices/ovs/nm-ovsdb.c b/src/core/devices/ovs/nm-ovsdb.c index 27ef789f..da3a7989 100644 --- a/src/devices/ovs/nm-ovsdb.c +++ b/src/core/devices/ovs/nm-ovsdb.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ovsdb.h" @@ -11,9 +11,16 @@ #include <gio/gunixsocketaddress.h> #include "nm-glib-aux/nm-jansson.h" +#include "nm-glib-aux/nm-str-buf.h" #include "nm-core-utils.h" #include "nm-core-internal.h" #include "devices/nm-device.h" +#include "nm-manager.h" +#include "nm-setting-ovs-external-ids.h" + +/*****************************************************************************/ + +#define OVSDB_MAX_FAILURES 3 /*****************************************************************************/ @@ -22,26 +29,91 @@ #endif typedef struct { + char * port_uuid; char * name; char * connection_uuid; GPtrArray *interfaces; /* interface uuids */ + GArray * external_ids; } OpenvswitchPort; typedef struct { + char * bridge_uuid; char * name; char * connection_uuid; GPtrArray *ports; /* port uuids */ + GArray * external_ids; } OpenvswitchBridge; typedef struct { - char *name; - char *type; - char *connection_uuid; + char * interface_uuid; + char * name; + char * type; + char * connection_uuid; + GArray *external_ids; } OpenvswitchInterface; /*****************************************************************************/ -enum { DEVICE_ADDED, DEVICE_REMOVED, INTERFACE_FAILED, LAST_SIGNAL }; +typedef void (*OvsdbMethodCallback)(NMOvsdb *self, + json_t * response, + GError * error, + gpointer user_data); + +typedef enum { + OVSDB_MONITOR, + OVSDB_ADD_INTERFACE, + OVSDB_DEL_INTERFACE, + OVSDB_SET_INTERFACE_MTU, + OVSDB_SET_EXTERNAL_IDS, +} OvsdbCommand; + +#define CALL_ID_UNSPEC G_MAXUINT64 + +typedef union { + struct { + } monitor; + struct { + NMConnection *bridge; + NMConnection *port; + NMConnection *interface; + NMDevice * bridge_device; + NMDevice * interface_device; + } add_interface; + struct { + char *ifname; + } del_interface; + struct { + char * ifname; + guint32 mtu; + } set_interface_mtu; + struct { + NMDeviceType device_type; + char * ifname; + char * connection_uuid; + GHashTable * exid_old; + GHashTable * exid_new; + } set_external_ids; +} OvsdbMethodPayload; + +typedef struct { + NMOvsdb * self; + CList calls_lst; + guint64 call_id; + OvsdbCommand command; + OvsdbMethodCallback callback; + gpointer user_data; + OvsdbMethodPayload payload; +} OvsdbMethodCall; + +/*****************************************************************************/ + +enum { + DEVICE_ADDED, + DEVICE_REMOVED, + INTERFACE_FAILED, + READY, + LAST_SIGNAL, +}; static guint signals[LAST_SIGNAL] = {0}; @@ -53,13 +125,17 @@ typedef struct { size_t bufp; /* Last decoded byte in the input buffer. */ GString * input; /* JSON stream waiting for decoding. */ GString * output; /* JSON stream to be sent. */ - gint64 seq; - GArray * calls; /* Method calls waiting for a response. */ - GHashTable * interfaces; /* interface uuid => OpenvswitchInterface */ - GHashTable * ports; /* port uuid => OpenvswitchPort */ - GHashTable * bridges; /* bridge uuid => OpenvswitchBridge */ - char * db_uuid; - guint num_failures; + guint64 call_id_counter; + + CList calls_lst_head; + + GHashTable *interfaces; /* interface uuid => OpenvswitchInterface */ + GHashTable *ports; /* port uuid => OpenvswitchPort */ + GHashTable *bridges; /* bridge uuid => OpenvswitchBridge */ + char * db_uuid; + guint num_failures; + guint num_pending_deletions; + bool ready : 1; } NMOvsdbPrivate; struct _NMOvsdb { @@ -75,9 +151,6 @@ G_DEFINE_TYPE(NMOvsdb, nm_ovsdb, G_TYPE_OBJECT) #define NM_OVSDB_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMOvsdb, NM_IS_OVSDB) -#define _NMLOG_DOMAIN LOGD_DEVICE -#define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__) - NM_DEFINE_SINGLETON_GETTER(NMOvsdb, nm_ovsdb_get, NM_TYPE_OVSDB); /*****************************************************************************/ @@ -90,89 +163,198 @@ static void ovsdb_next_command(NMOvsdb *self); /*****************************************************************************/ -/* ovsdb command abstraction. */ +#define _NMLOG_DOMAIN LOGD_DEVICE +#define _NMLOG(level, ...) __NMLOG_DEFAULT(level, _NMLOG_DOMAIN, "ovsdb", __VA_ARGS__) -typedef void (*OvsdbMethodCallback)(NMOvsdb *self, - json_t * response, - GError * error, - gpointer user_data); +#define _NMLOG_call(level, call, ...) \ + _NMLOG((level), \ + "call[" NM_HASH_OBFUSCATE_PTR_FMT "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR((call)) _NM_UTILS_MACRO_REST(__VA_ARGS__)) -typedef enum { - OVSDB_MONITOR, - OVSDB_ADD_INTERFACE, - OVSDB_DEL_INTERFACE, - OVSDB_SET_INTERFACE_MTU, -} OvsdbCommand; +#define _LOGT_call(call, ...) _NMLOG_call(LOGL_TRACE, (call), __VA_ARGS__) -typedef struct { - gint64 id; -#define COMMAND_PENDING -1 /* id not yet assigned */ - OvsdbCommand command; - OvsdbMethodCallback callback; - gpointer user_data; - union { - struct { - char * ifname; - guint32 mtu; - }; - struct { - NMConnection *bridge; - NMConnection *port; - NMConnection *interface; - NMDevice * bridge_device; - NMDevice * interface_device; - }; - }; -} OvsdbMethodCall; +/*****************************************************************************/ -#define OVSDB_MAX_FAILURES 3 +#define OVSDB_METHOD_PAYLOAD_MONITOR() \ + (&((const OvsdbMethodPayload){ \ + .monitor = {}, \ + })) + +#define OVSDB_METHOD_PAYLOAD_ADD_INTERFACE(xbridge, \ + xport, \ + xinterface, \ + xbridge_device, \ + xinterface_device) \ + (&((const OvsdbMethodPayload){ \ + .add_interface = \ + { \ + .bridge = (xbridge), \ + .port = (xport), \ + .interface = (xinterface), \ + .bridge_device = (xbridge_device), \ + .interface_device = (xinterface_device), \ + }, \ + })) + +#define OVSDB_METHOD_PAYLOAD_DEL_INTERFACE(xifname) \ + (&((const OvsdbMethodPayload){ \ + .del_interface = \ + { \ + .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ + }, \ + })) + +#define OVSDB_METHOD_PAYLOAD_SET_INTERFACE_MTU(xifname, xmtu) \ + (&((const OvsdbMethodPayload){ \ + .set_interface_mtu = \ + { \ + .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ + .mtu = (xmtu), \ + }, \ + })) + +#define OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(xdevice_type, \ + xifname, \ + xconnection_uuid, \ + xexid_old, \ + xexid_new) \ + (&((const OvsdbMethodPayload){ \ + .set_external_ids = \ + { \ + .device_type = xdevice_type, \ + .ifname = (char *) NM_CONSTCAST(char, (xifname)), \ + .connection_uuid = (char *) NM_CONSTCAST(char, (xconnection_uuid)), \ + .exid_old = (xexid_old), \ + .exid_new = (xexid_new), \ + }, \ + })) + +/*****************************************************************************/ + +static NM_UTILS_LOOKUP_STR_DEFINE(_device_type_to_table, + NMDeviceType, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(NULL), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_BRIDGE, "Bridge"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_PORT, "Port"), + NM_UTILS_LOOKUP_STR_ITEM(NM_DEVICE_TYPE_OVS_INTERFACE, + "Interface"), + NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), ); + +/*****************************************************************************/ static void -_LOGT_call_do(const char *comment, OvsdbMethodCall *call, json_t *msg) +_call_complete(OvsdbMethodCall *call, json_t *response, GError *error) { - gs_free char *str = NULL; + if (response) { + gs_free char *str = NULL; + + str = json_dumps(response, 0); + if (error) + _LOGT_call(call, "completed: %s ; error: %s", str, error->message); + else + _LOGT_call(call, "completed: %s", str); + } else { + nm_assert(error); + _LOGT_call(call, "completed: error: %s", error->message); + } + + c_list_unlink_stale(&call->calls_lst); - if (msg) - str = json_dumps(msg, 0); + if (call->callback) + call->callback(call->self, response, error, call->user_data); switch (call->command) { case OVSDB_MONITOR: - _LOGT("%s: monitor%s%s", comment, msg ? ": " : "", msg ? str : ""); break; case OVSDB_ADD_INTERFACE: - _LOGT("%s: add-iface bridge=%s port=%s interface=%s%s%s", - comment, - nm_connection_get_interface_name(call->bridge), - nm_connection_get_interface_name(call->port), - nm_connection_get_interface_name(call->interface), - msg ? ": " : "", - msg ? str : ""); + g_clear_object(&call->payload.add_interface.bridge); + g_clear_object(&call->payload.add_interface.port); + g_clear_object(&call->payload.add_interface.interface); + g_clear_object(&call->payload.add_interface.bridge_device); + g_clear_object(&call->payload.add_interface.interface_device); break; case OVSDB_DEL_INTERFACE: - _LOGT("%s: del-iface interface=%s%s%s", - comment, - call->ifname, - msg ? ": " : "", - msg ? str : ""); + nm_clear_g_free(&call->payload.del_interface.ifname); break; case OVSDB_SET_INTERFACE_MTU: - _LOGT("%s: set-iface-mtu interface=%s%s%s mtu=%u", - comment, - call->ifname, - msg ? ": " : "", - msg ? str : "", - call->mtu); + nm_clear_g_free(&call->payload.set_interface_mtu.ifname); + break; + case OVSDB_SET_EXTERNAL_IDS: + nm_clear_g_free(&call->payload.set_external_ids.ifname); + nm_clear_g_free(&call->payload.set_external_ids.connection_uuid); + nm_clear_pointer(&call->payload.set_external_ids.exid_old, g_hash_table_destroy); + nm_clear_pointer(&call->payload.set_external_ids.exid_new, g_hash_table_destroy); break; } + + nm_g_slice_free(call); +} + +/*****************************************************************************/ + +static void +_free_bridge(OpenvswitchBridge *ovs_bridge) +{ + g_free(ovs_bridge->bridge_uuid); + g_free(ovs_bridge->name); + g_free(ovs_bridge->connection_uuid); + g_ptr_array_free(ovs_bridge->ports, TRUE); + nm_g_array_unref(ovs_bridge->external_ids); + nm_g_slice_free(ovs_bridge); } -#define _LOGT_call(comment, call, message) \ - G_STMT_START \ - { \ - if (_LOGT_ENABLED()) \ - _LOGT_call_do((comment), (call), (message)); \ - } \ - G_STMT_END +static void +_free_port(OpenvswitchPort *ovs_port) +{ + g_free(ovs_port->port_uuid); + g_free(ovs_port->name); + g_free(ovs_port->connection_uuid); + g_ptr_array_free(ovs_port->interfaces, TRUE); + nm_g_array_unref(ovs_port->external_ids); + nm_g_slice_free(ovs_port); +} + +static void +_free_interface(OpenvswitchInterface *ovs_interface) +{ + g_free(ovs_interface->interface_uuid); + g_free(ovs_interface->name); + g_free(ovs_interface->connection_uuid); + g_free(ovs_interface->type); + nm_g_array_unref(ovs_interface->external_ids); + nm_g_slice_free(ovs_interface); +} + +/*****************************************************************************/ + +static void +_signal_emit_device_added(NMOvsdb * self, + const char * name, + NMDeviceType device_type, + const char * device_subtype) +{ + g_signal_emit(self, signals[DEVICE_ADDED], 0, name, (guint) device_type, device_subtype); +} + +static void +_signal_emit_device_removed(NMOvsdb * self, + const char * name, + NMDeviceType device_type, + const char * device_subtype) +{ + g_signal_emit(self, signals[DEVICE_REMOVED], 0, name, (guint) device_type, device_subtype); +} + +static void +_signal_emit_interface_failed(NMOvsdb * self, + const char *name, + const char *connection_uuid, + const char *error) +{ + g_signal_emit(self, signals[INTERFACE_FAILED], 0, name, connection_uuid, error); +} + +/*****************************************************************************/ /** * ovsdb_call_method: @@ -181,18 +363,12 @@ _LOGT_call_do(const char *comment, OvsdbMethodCall *call, json_t *msg) * there's no command pending completion. */ static void -ovsdb_call_method(NMOvsdb * self, - OvsdbCommand command, - const char * ifname, - NMConnection * bridge, - NMConnection * port, - NMConnection * interface, - NMDevice * bridge_device, - NMDevice * interface_device, - guint32 mtu, - OvsdbMethodCallback callback, - gpointer user_data, - gboolean add_first) +ovsdb_call_method(NMOvsdb * self, + OvsdbMethodCallback callback, + gpointer user_data, + gboolean add_first, + OvsdbCommand command, + const OvsdbMethodPayload *payload) { NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); OvsdbMethodCall *call; @@ -200,39 +376,76 @@ ovsdb_call_method(NMOvsdb * self, /* Ensure we're not unsynchronized before we queue the method call. */ ovsdb_try_connect(self); - if (add_first) { - g_array_prepend_val(priv->calls, (OvsdbMethodCall){}); - call = &g_array_index(priv->calls, OvsdbMethodCall, 0); - } else { - g_array_set_size(priv->calls, priv->calls->len + 1); - call = &g_array_index(priv->calls, OvsdbMethodCall, priv->calls->len - 1); - } - call->id = COMMAND_PENDING; - call->command = command; - call->callback = callback; - call->user_data = user_data; + call = g_slice_new(OvsdbMethodCall); + *call = (OvsdbMethodCall){ + .self = self, + .call_id = CALL_ID_UNSPEC, + .command = command, + .callback = callback, + .user_data = user_data, + }; - switch (call->command) { + if (add_first) + c_list_link_front(&priv->calls_lst_head, &call->calls_lst); + else + c_list_link_tail(&priv->calls_lst_head, &call->calls_lst); + + /* Migrate the arguments from @payload to @call->payload. Technically, + * this is not a plain copy, because + * - call->payload is not initialized (thus no need to free the previous data). + * - payload does not own the data. It is merely initialized using the + * OVSDB_METHOD_PAYLOAD_*() macros. */ + switch (command) { case OVSDB_MONITOR: + _LOGT_call(call, "new: monitor"); break; case OVSDB_ADD_INTERFACE: - call->bridge = nm_simple_connection_new_clone(bridge); - call->port = nm_simple_connection_new_clone(port); - call->interface = nm_simple_connection_new_clone(interface); - call->bridge_device = g_object_ref(bridge_device); - call->interface_device = g_object_ref(interface_device); + /* FIXME(applied-connection-immutable): we should not modify the applied + * connection, consequently there is no need to clone the connections. */ + call->payload.add_interface.bridge = + nm_simple_connection_new_clone(payload->add_interface.bridge); + call->payload.add_interface.port = + nm_simple_connection_new_clone(payload->add_interface.port); + call->payload.add_interface.interface = + nm_simple_connection_new_clone(payload->add_interface.interface); + call->payload.add_interface.bridge_device = + g_object_ref(payload->add_interface.bridge_device); + call->payload.add_interface.interface_device = + g_object_ref(payload->add_interface.interface_device); + _LOGT_call(call, + "new: add-interface bridge=%s port=%s interface=%s", + nm_connection_get_interface_name(call->payload.add_interface.bridge), + nm_connection_get_interface_name(call->payload.add_interface.port), + nm_connection_get_interface_name(call->payload.add_interface.interface)); break; case OVSDB_DEL_INTERFACE: - call->ifname = g_strdup(ifname); + call->payload.del_interface.ifname = g_strdup(payload->del_interface.ifname); + _LOGT_call(call, "new: del-interface interface=%s", call->payload.del_interface.ifname); break; case OVSDB_SET_INTERFACE_MTU: - call->ifname = g_strdup(ifname); - call->mtu = mtu; + call->payload.set_interface_mtu.ifname = g_strdup(payload->set_interface_mtu.ifname); + call->payload.set_interface_mtu.mtu = payload->set_interface_mtu.mtu; + _LOGT_call(call, + "new: set-interface-mtu interface=%s mtu=%u", + call->payload.set_interface_mtu.ifname, + call->payload.set_interface_mtu.mtu); + break; + case OVSDB_SET_EXTERNAL_IDS: + call->payload.set_external_ids.device_type = payload->set_external_ids.device_type; + call->payload.set_external_ids.ifname = g_strdup(payload->set_external_ids.ifname); + call->payload.set_external_ids.connection_uuid = + g_strdup(payload->set_external_ids.connection_uuid); + call->payload.set_external_ids.exid_old = + nm_g_hash_table_ref(payload->set_external_ids.exid_old); + call->payload.set_external_ids.exid_new = + nm_g_hash_table_ref(payload->set_external_ids.exid_new); + _LOGT_call(call, + "new: set-external-ids con-uuid=%s, interface=%s", + call->payload.set_external_ids.connection_uuid, + call->payload.set_external_ids.ifname); break; } - _LOGT_call("enqueue", call, NULL); - ovsdb_next_command(self); } @@ -437,6 +650,94 @@ _set_port_interfaces(json_t *params, const char *ifname, json_t *new_interfaces) ifname)); } +static json_t * +_j_create_external_ids_array_new(NMConnection *connection) +{ + json_t * array; + const char *const * external_ids = NULL; + guint n_external_ids = 0; + guint i; + const char * uuid; + NMSettingOvsExternalIDs *s_exid; + + nm_assert(NM_IS_CONNECTION(connection)); + + array = json_array(); + + uuid = nm_connection_get_uuid(connection); + nm_assert(uuid); + json_array_append_new(array, json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, uuid)); + + s_exid = _nm_connection_get_setting(connection, NM_TYPE_SETTING_OVS_EXTERNAL_IDS); + if (s_exid) + external_ids = nm_setting_ovs_external_ids_get_data_keys(s_exid, &n_external_ids); + for (i = 0; i < n_external_ids; i++) { + const char *k = external_ids[i]; + + json_array_append_new( + array, + json_pack("[s, s]", k, nm_setting_ovs_external_ids_get_data(s_exid, k))); + } + + return json_pack("[s, o]", "map", array); +} + +static json_t * +_j_create_external_ids_array_update(const char *connection_uuid, + GHashTable *exid_old, + GHashTable *exid_new) +{ + GHashTableIter iter; + json_t * mutations; + json_t * array; + const char * key; + const char * val; + + nm_assert(connection_uuid); + + mutations = json_array(); + + if (exid_old) { + array = NULL; + g_hash_table_iter_init(&iter, exid_old); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, NULL)) { + if (nm_g_hash_table_contains(exid_new, key)) + continue; + if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) + continue; + + if (!array) + array = json_array(); + + json_array_append_new(array, json_string(key)); + } + if (array) { + json_array_append_new( + mutations, + json_pack("[s, s, [s, o]]", "external_ids", "delete", "set", array)); + } + } + + array = json_array(); + + json_array_append_new( + array, + json_pack("[s, s]", NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID, connection_uuid)); + + if (exid_new) { + g_hash_table_iter_init(&iter, exid_new); + while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val)) { + if (NM_STR_HAS_PREFIX(key, NM_OVS_EXTERNAL_ID_NM_PREFIX)) + continue; + json_array_append_new(array, json_pack("[s, s]", key, val)); + } + } + + json_array_append_new(mutations, + json_pack("[s, s, [s, o]]", "external_ids", "insert", "map", array)); + return mutations; +} + /** * _insert_interface: * @@ -487,7 +788,7 @@ _insert_interface(json_t * params, json_array_append_new(options, json_array()); } - row = json_pack("{s:s, s:s, s:o, s:[s, [[s, s]]]}", + row = json_pack("{s:s, s:s, s:o, s:o}", "name", nm_connection_get_interface_name(interface), "type", @@ -495,9 +796,7 @@ _insert_interface(json_t * params, "options", options, "external_ids", - "map", - "NM.connection.uuid", - nm_connection_get_uuid(interface)); + _j_create_external_ids_array_new(interface)); if (cloned_mac) json_object_set_new(row, "mac", json_string(cloned_mac)); @@ -562,10 +861,7 @@ _insert_port(json_t *params, NMConnection *port, json_t *new_interfaces) json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(port))); json_object_set_new(row, "interfaces", json_pack("[s, O]", "set", new_interfaces)); - json_object_set_new( - row, - "external_ids", - json_pack("[s, [[s, s]]]", "map", "NM.connection.uuid", nm_connection_get_uuid(port))); + json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(port)); /* Create a new one. */ json_array_append_new(params, @@ -625,10 +921,7 @@ _insert_bridge(json_t * params, json_object_set_new(row, "name", json_string(nm_connection_get_interface_name(bridge))); json_object_set_new(row, "ports", json_pack("[s, O]", "set", new_ports)); - json_object_set_new( - row, - "external_ids", - json_pack("[s, [[s, s]]]", "map", "NM.connection.uuid", nm_connection_get_uuid(bridge))); + json_object_set_new(row, "external_ids", _j_create_external_ids_array_new(bridge)); if (cloned_mac) { json_object_set_new(row, @@ -691,7 +984,6 @@ _add_interface(NMOvsdb * self, { NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); GHashTableIter iter; - const char * bridge_uuid; const char * port_uuid; const char * interface_uuid; const char * bridge_name; @@ -777,43 +1069,43 @@ _add_interface(NMOvsdb * self, } g_hash_table_iter_init(&iter, priv->bridges); - while (g_hash_table_iter_next(&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { - json_array_append_new(bridges, json_pack("[s, s]", "uuid", bridge_uuid)); + while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) { + json_array_append_new(bridges, json_pack("[s, s]", "uuid", ovs_bridge->bridge_uuid)); - if (g_strcmp0(ovs_bridge->name, bridge_name) != 0 - || g_strcmp0(ovs_bridge->connection_uuid, nm_connection_get_uuid(bridge)) != 0) + if (!nm_streq0(ovs_bridge->name, bridge_name) + || !nm_streq0(ovs_bridge->connection_uuid, nm_connection_get_uuid(bridge))) continue; for (pi = 0; pi < ovs_bridge->ports->len; pi++) { port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); - ovs_port = g_hash_table_lookup(priv->ports, port_uuid); + ovs_port = g_hash_table_lookup(priv->ports, &port_uuid); json_array_append_new(ports, json_pack("[s, s]", "uuid", port_uuid)); if (!ovs_port) { /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); - continue; - } else if (strcmp(ovs_port->name, port_name) != 0 - || g_strcmp0(ovs_port->connection_uuid, nm_connection_get_uuid(port)) != 0) { + _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid); continue; } + if (!nm_streq(ovs_port->name, port_name) + || !nm_streq0(ovs_port->connection_uuid, nm_connection_get_uuid(port))) + continue; + for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); - ovs_interface = g_hash_table_lookup(priv->interfaces, interface_uuid); + ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid); json_array_append_new(interfaces, json_pack("[s, s]", "uuid", interface_uuid)); if (!ovs_interface) { /* This would be a violation of ovsdb's reference integrity (a bug). */ _LOGW("Unknown interface '%s' in port '%s'", interface_uuid, port_uuid); - } else if (strcmp(ovs_interface->name, interface_name) == 0 - && g_strcmp0(ovs_interface->connection_uuid, - nm_connection_get_uuid(interface)) - == 0) { - has_interface = TRUE; + continue; } + if (nm_streq(ovs_interface->name, interface_name) + && nm_streq0(ovs_interface->connection_uuid, nm_connection_get_uuid(interface))) + has_interface = TRUE; } break; @@ -869,7 +1161,6 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) { NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); GHashTableIter iter; - char * bridge_uuid; char * port_uuid; char * interface_uuid; OpenvswitchBridge * ovs_bridge; @@ -888,7 +1179,7 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) bridges_changed = FALSE; g_hash_table_iter_init(&iter, priv->bridges); - while (g_hash_table_iter_next(&iter, (gpointer) &bridge_uuid, (gpointer) &ovs_bridge)) { + while (g_hash_table_iter_next(&iter, (gpointer) &ovs_bridge, NULL)) { nm_auto_decref_json json_t *ports = NULL; nm_auto_decref_json json_t *new_ports = NULL; @@ -896,7 +1187,7 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) new_ports = json_array(); ports_changed = FALSE; - json_array_append_new(bridges, json_pack("[s,s]", "uuid", bridge_uuid)); + json_array_append_new(bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); for (pi = 0; pi < ovs_bridge->ports->len; pi++) { nm_auto_decref_json json_t *interfaces = NULL; @@ -905,7 +1196,7 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) interfaces = json_array(); new_interfaces = json_array(); port_uuid = g_ptr_array_index(ovs_bridge->ports, pi); - ovs_port = g_hash_table_lookup(priv->ports, port_uuid); + ovs_port = g_hash_table_lookup(priv->ports, &port_uuid); json_array_append_new(ports, json_pack("[s,s]", "uuid", port_uuid)); @@ -913,18 +1204,18 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) if (!ovs_port) { /* This would be a violation of ovsdb's reference integrity (a bug). */ - _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, bridge_uuid); + _LOGW("Unknown port '%s' in bridge '%s'", port_uuid, ovs_bridge->bridge_uuid); continue; } for (ii = 0; ii < ovs_port->interfaces->len; ii++) { interface_uuid = g_ptr_array_index(ovs_port->interfaces, ii); - ovs_interface = g_hash_table_lookup(priv->interfaces, interface_uuid); + ovs_interface = g_hash_table_lookup(priv->interfaces, &interface_uuid); json_array_append_new(interfaces, json_pack("[s,s]", "uuid", interface_uuid)); if (ovs_interface) { - if (strcmp(ovs_interface->name, ifname) == 0) { + if (nm_streq(ovs_interface->name, ifname)) { /* skip the interface */ interfaces_changed = TRUE; continue; @@ -955,7 +1246,7 @@ _delete_interface(NMOvsdb *self, json_t *params, const char *ifname) _expect_bridge_ports(params, ovs_bridge->name, ports); _set_bridge_ports(params, ovs_bridge->name, new_ports); } - json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", bridge_uuid)); + json_array_append_new(new_bridges, json_pack("[s,s]", "uuid", ovs_bridge->bridge_uuid)); } } @@ -979,30 +1270,32 @@ static void ovsdb_next_command(NMOvsdb *self) { NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - OvsdbMethodCall * call = NULL; + OvsdbMethodCall * call; char * cmd; nm_auto_decref_json json_t *msg = NULL; - json_t * params; if (!priv->conn) return; - if (!priv->calls->len) + + if (c_list_is_empty(&priv->calls_lst_head)) return; - call = &g_array_index(priv->calls, OvsdbMethodCall, 0); - if (call->id != COMMAND_PENDING) + + call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst); + if (call->call_id != CALL_ID_UNSPEC) return; - call->id = priv->seq++; + + call->call_id = ++priv->call_id_counter; switch (call->command) { case OVSDB_MONITOR: - msg = json_pack("{s:i, s:s, s:[s, n, {" + msg = json_pack("{s:I, s:s, s:[s, n, {" " s:[{s:[s, s, s]}]," " s:[{s:[s, s, s]}]," " s:[{s:[s, s, s, s]}]," " s:[{s:[]}]" "}]}", "id", - call->id, + (json_int_t) call->call_id, "method", "monitor", "params", @@ -1026,57 +1319,81 @@ ovsdb_next_command(NMOvsdb *self) "Open_vSwitch", "columns"); break; - case OVSDB_ADD_INTERFACE: - params = json_array(); - json_array_append_new(params, json_string("Open_vSwitch")); - json_array_append_new(params, _inc_next_cfg(priv->db_uuid)); - - _add_interface(self, - params, - call->bridge, - call->port, - call->interface, - call->bridge_device, - call->interface_device); + default: + { + json_t *params = NULL; - msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); - break; - case OVSDB_DEL_INTERFACE: params = json_array(); json_array_append_new(params, json_string("Open_vSwitch")); json_array_append_new(params, _inc_next_cfg(priv->db_uuid)); - _delete_interface(self, params, call->ifname); + switch (call->command) { + case OVSDB_ADD_INTERFACE: + _add_interface(self, + params, + call->payload.add_interface.bridge, + call->payload.add_interface.port, + call->payload.add_interface.interface, + call->payload.add_interface.bridge_device, + call->payload.add_interface.interface_device); + break; + case OVSDB_DEL_INTERFACE: + _delete_interface(self, params, call->payload.del_interface.ifname); + break; + case OVSDB_SET_INTERFACE_MTU: + json_array_append_new(params, + json_pack("{s:s, s:s, s:{s: I}, s:[[s, s, s]]}", + "op", + "update", + "table", + "Interface", + "row", + "mtu_request", + (json_int_t) call->payload.set_interface_mtu.mtu, + "where", + "name", + "==", + call->payload.set_interface_mtu.ifname)); + break; + case OVSDB_SET_EXTERNAL_IDS: + json_array_append_new( + params, + json_pack("{s:s, s:s, s:o, s:[[s, s, s]]}", + "op", + "mutate", + "table", + _device_type_to_table(call->payload.set_external_ids.device_type), + "mutations", + _j_create_external_ids_array_update( + call->payload.set_external_ids.connection_uuid, + call->payload.set_external_ids.exid_old, + call->payload.set_external_ids.exid_new), + "where", + "name", + "==", + call->payload.set_external_ids.ifname)); + break; - msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); - break; - case OVSDB_SET_INTERFACE_MTU: - params = json_array(); - json_array_append_new(params, json_string("Open_vSwitch")); - json_array_append_new(params, _inc_next_cfg(priv->db_uuid)); + default: + nm_assert_not_reached(); + break; + } - json_array_append_new(params, - json_pack("{s:s, s:s, s:{s: i}, s:[[s, s, s]]}", - "op", - "update", - "table", - "Interface", - "row", - "mtu_request", - call->mtu, - "where", - "name", - "==", - call->ifname)); - - msg = json_pack("{s:i, s:s, s:o}", "id", call->id, "method", "transact", "params", params); + msg = json_pack("{s:I, s:s, s:o}", + "id", + (json_int_t) call->call_id, + "method", + "transact", + "params", + params); break; } + } g_return_if_fail(msg); - _LOGT_call("send", call, msg); - cmd = json_dumps(msg, 0); + cmd = json_dumps(msg, 0); + _LOGT_call(call, "send: call-id=%" G_GUINT64_FORMAT ", %s", call->call_id, cmd); g_string_append(priv->output, cmd); free(cmd); @@ -1097,7 +1414,7 @@ ovsdb_next_command(NMOvsdb *self) * [ "uuid", "185c93f6-0b39-424e-8587-77d074aa7ce0" ], ... ] ] */ static void -_uuids_to_array(GPtrArray *array, const json_t *items) +_uuids_to_array_inplace(GPtrArray *array, const json_t *items) { const char *key; json_t * value; @@ -1111,38 +1428,123 @@ _uuids_to_array(GPtrArray *array, const json_t *items) value = json_array_get(items, index); index++; - if (!value) + if (!value || !key) return; - if (g_strcmp0(key, "uuid") == 0 && json_is_string(value)) { - g_ptr_array_add(array, g_strdup(json_string_value(value))); - } else if (g_strcmp0(key, "set") == 0 && json_is_array(value)) { - json_array_foreach(value, set_index, set_value) - { - _uuids_to_array(array, set_value); + if (nm_streq(key, "uuid")) { + if (json_is_string(value)) + g_ptr_array_add(array, g_strdup(json_string_value(value))); + continue; + } + if (nm_streq(key, "set")) { + if (json_is_array(value)) { + json_array_foreach (value, set_index, set_value) + _uuids_to_array_inplace(array, set_value); } + continue; } } } -static char * -_connection_uuid_from_external_ids(json_t *external_ids) +static GPtrArray * +_uuids_to_array(const json_t *items) { + GPtrArray *array; + + array = g_ptr_array_new_with_free_func(g_free); + _uuids_to_array_inplace(array, items); + return array; +} + +static void +_external_ids_extract(json_t *external_ids, GArray **out_array, const char **out_connection_uuid) +{ + json_t *array; json_t *value; - size_t index; + gsize index; - if (g_strcmp0("map", json_string_value(json_array_get(external_ids, 0))) != 0) - return NULL; + nm_assert(out_array && !*out_array); + nm_assert(!out_connection_uuid || !*out_connection_uuid); - json_array_foreach(json_array_get(external_ids, 1), index, value) - { - if (g_strcmp0("NM.connection.uuid", json_string_value(json_array_get(value, 0))) == 0) - return g_strdup(json_string_value(json_array_get(value, 1))); + if (!nm_streq0("map", json_string_value(json_array_get(external_ids, 0)))) + return; + + array = json_array_get(external_ids, 1); + + json_array_foreach (array, index, value) { + const char * key = json_string_value(json_array_get(value, 0)); + const char * val = json_string_value(json_array_get(value, 1)); + NMUtilsNamedValue *v; + + if (!key || !val) + continue; + + if (!*out_array) { + *out_array = g_array_new(FALSE, FALSE, sizeof(NMUtilsNamedValue)); + g_array_set_clear_func(*out_array, + (GDestroyNotify) nm_utils_named_value_clear_with_g_free); + } + + v = nm_g_array_append_new(*out_array, NMUtilsNamedValue); + *v = (NMUtilsNamedValue){ + .name = g_strdup(key), + .value_str = g_strdup(val), + }; + + if (out_connection_uuid && nm_streq(v->name, NM_OVS_EXTERNAL_ID_NM_CONNECTION_UUID)) { + *out_connection_uuid = v->value_str; + out_connection_uuid = NULL; + } } +} + +static gboolean +_external_ids_equal(const GArray *arr1, const GArray *arr2) +{ + guint n; + guint i; - return NULL; + n = nm_g_array_len(arr1); + + if (n != nm_g_array_len(arr2)) + return FALSE; + for (i = 0; i < n; i++) { + const NMUtilsNamedValue *n1 = &g_array_index(arr1, NMUtilsNamedValue, i); + const NMUtilsNamedValue *n2 = &g_array_index(arr2, NMUtilsNamedValue, i); + + if (!nm_streq0(n1->name, n2->name)) + return FALSE; + if (!nm_streq0(n1->value_str, n2->value_str)) + return FALSE; + } + return TRUE; } +static char * +_external_ids_to_string(const GArray *arr) +{ + NMStrBuf strbuf; + guint i; + + if (!arr) + return g_strdup("empty"); + + nm_str_buf_init(&strbuf, NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + nm_str_buf_append(&strbuf, "["); + for (i = 0; i < arr->len; i++) { + const NMUtilsNamedValue *n = &g_array_index(arr, NMUtilsNamedValue, i); + + if (i > 0) + nm_str_buf_append_c(&strbuf, ','); + nm_str_buf_append_printf(&strbuf, " \"%s\" = \"%s\"]", n->name, n->value_str); + } + nm_str_buf_append(&strbuf, " ]"); + + return nm_str_buf_finalize(&strbuf, NULL); +} + +/*****************************************************************************/ + /** * ovsdb_got_update: * @@ -1163,14 +1565,11 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) json_error_t json_error = { 0, }; - void * iter; - const char * name; - const char * key; - const char * type; - json_t * value; - OpenvswitchBridge * ovs_bridge; - OpenvswitchPort * ovs_port; - OpenvswitchInterface *ovs_interface; + void * iter; + const char *name; + const char *key; + const char *type; + json_t * value; if (json_unpack_ex(msg, &json_error, @@ -1199,17 +1598,14 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) nm_utils_strdup_reset(&priv->db_uuid, s); } - /* Interfaces */ - json_object_foreach(interface, key, value) - { - json_t * error = NULL; - gboolean old = FALSE; - gboolean new = FALSE; - - if (json_unpack(value, "{s:{}}", "old") == 0) - old = TRUE; + json_object_foreach (interface, key, value) { + OpenvswitchInterface *ovs_interface; + gs_unref_array GArray *external_ids_arr = NULL; + const char * connection_uuid = NULL; + json_t * error = NULL; + int r; - if (json_unpack(value, + r = json_unpack(value, "{s:{s:s, s:s, s?:o, s:o}}", "new", "name", @@ -1219,85 +1615,120 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) "error", &error, "external_ids", - &external_ids) - == 0) - new = TRUE; - - if (old) { - ovs_interface = g_hash_table_lookup(priv->interfaces, key); - if (!ovs_interface) { - _LOGW("Interface '%s' was not seen", key); - } else if (!new || strcmp(ovs_interface->name, name) != 0) { - old = FALSE; - _LOGT("removed an '%s' interface: %s%s%s", - ovs_interface->type, - ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - if (g_strcmp0(ovs_interface->type, "internal") == 0) { - /* Currently, the factory only creates NMDevices for - * internal interfaces. Ignore the rest. */ - g_signal_emit(self, - signals[DEVICE_REMOVED], - 0, - ovs_interface->name, - NM_DEVICE_TYPE_OVS_INTERFACE); - } - } - g_hash_table_remove(priv->interfaces, key); + &external_ids); + if (r != 0) { + gpointer unused; + + r = json_unpack(value, "{s:{}}", "old"); + if (r != 0) + continue; + + if (!g_hash_table_steal_extended(priv->interfaces, + &key, + (gpointer *) &ovs_interface, + &unused)) + continue; + + _LOGT("obj[iface:%s]: removed an '%s' interface: %s%s%s", + key, + ovs_interface->type, + ovs_interface->name, + NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid, + ", ", + ovs_interface->connection_uuid, + "")); + _signal_emit_device_removed(self, + ovs_interface->name, + NM_DEVICE_TYPE_OVS_INTERFACE, + ovs_interface->type); + _free_interface(ovs_interface); + continue; } - if (new) { - ovs_interface = g_slice_new(OpenvswitchInterface); - ovs_interface->name = g_strdup(name); - ovs_interface->type = g_strdup(type); - ovs_interface->connection_uuid = _connection_uuid_from_external_ids(external_ids); - g_hash_table_insert(priv->interfaces, g_strdup(key), ovs_interface); - if (old) { - _LOGT("changed an '%s' interface: %s%s%s", + ovs_interface = g_hash_table_lookup(priv->interfaces, &key); + + if (ovs_interface + && (!nm_streq0(ovs_interface->name, name) || !nm_streq0(ovs_interface->type, type))) { + if (!g_hash_table_steal(priv->interfaces, ovs_interface)) + nm_assert_not_reached(); + _signal_emit_device_removed(self, + ovs_interface->name, + NM_DEVICE_TYPE_OVS_INTERFACE, + ovs_interface->type); + nm_clear_pointer(&ovs_interface, _free_interface); + } + + _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + + if (ovs_interface) { + gboolean changed = FALSE; + + nm_assert(nm_streq0(ovs_interface->name, name)); + + changed |= nm_utils_strdup_reset(&ovs_interface->type, type); + changed |= nm_utils_strdup_reset(&ovs_interface->connection_uuid, connection_uuid); + if (!_external_ids_equal(ovs_interface->external_ids, external_ids_arr)) { + NM_SWAP(&ovs_interface->external_ids, &external_ids_arr); + changed = TRUE; + } + if (changed) { + gs_free char *strtmp = NULL; + + _LOGT("obj[iface:%s]: changed an '%s' interface: %s%s%s, external-ids=%s", + key, type, ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - } else { - _LOGT("added an '%s' interface: %s%s%s", - ovs_interface->type, - ovs_interface->name, - ovs_interface->connection_uuid ? ", " : "", - ovs_interface->connection_uuid ?: ""); - if (g_strcmp0(ovs_interface->type, "internal") == 0) { - /* Currently, the factory only creates NMDevices for - * internal interfaces. Ignore the rest. */ - g_signal_emit(self, - signals[DEVICE_ADDED], - 0, - ovs_interface->name, - NM_DEVICE_TYPE_OVS_INTERFACE); - } - } - /* The error is a string. No error is indicated by an empty set, - * because why the fuck not: [ "set": [] ] */ - if (error && json_is_string(error)) { - g_signal_emit(self, - signals[INTERFACE_FAILED], - 0, - ovs_interface->name, - ovs_interface->connection_uuid, - json_string_value(error)); + NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid, + ", ", + ovs_interface->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_interface->external_ids))); } + } else { + gs_free char *strtmp = NULL; + + ovs_interface = g_slice_new(OpenvswitchInterface); + *ovs_interface = (OpenvswitchInterface){ + .interface_uuid = g_strdup(key), + .name = g_strdup(name), + .type = g_strdup(type), + .connection_uuid = g_strdup(connection_uuid), + .external_ids = g_steal_pointer(&external_ids_arr), + }; + g_hash_table_add(priv->interfaces, ovs_interface); + _LOGT("obj[iface:%s]: added an '%s' interface: %s%s%s, external-ids=%s", + key, + ovs_interface->type, + ovs_interface->name, + NM_PRINT_FMT_QUOTED2(ovs_interface->connection_uuid, + ", ", + ovs_interface->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_interface->external_ids))); + _signal_emit_device_added(self, + ovs_interface->name, + NM_DEVICE_TYPE_OVS_INTERFACE, + ovs_interface->type); } - } - /* Ports */ - json_object_foreach(port, key, value) - { - gboolean old = FALSE; - gboolean new = FALSE; + /* The error is a string. No error is indicated by an empty set, + * Why not: [ "set": [] ] ? */ + if (error && json_is_string(error)) { + _signal_emit_interface_failed(self, + ovs_interface->name, + ovs_interface->connection_uuid, + json_string_value(error)); + } + } - if (json_unpack(value, "{s:{}}", "old") == 0) - old = TRUE; + json_object_foreach (port, key, value) { + gs_unref_ptrarray GPtrArray *interfaces = NULL; + OpenvswitchPort * ovs_port; + gs_unref_array GArray *external_ids_arr = NULL; + const char * connection_uuid = NULL; + int r; - if (json_unpack(value, + r = json_unpack(value, "{s:{s:s, s:o, s:o}}", "new", "name", @@ -1305,63 +1736,100 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) "external_ids", &external_ids, "interfaces", - &items) - == 0) - new = TRUE; - - if (old) { - ovs_port = g_hash_table_lookup(priv->ports, key); - if (!new || g_strcmp0(ovs_port->name, name) != 0) { - old = FALSE; - _LOGT("removed a port: %s%s%s", - ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - g_signal_emit(self, - signals[DEVICE_REMOVED], - 0, - ovs_port->name, - NM_DEVICE_TYPE_OVS_PORT); - } - g_hash_table_remove(priv->ports, key); + &items); + if (r != 0) { + gpointer unused; + + r = json_unpack(value, "{s:{}}", "old"); + if (r != 0) + continue; + + if (!g_hash_table_steal_extended(priv->ports, &key, (gpointer *) &ovs_port, &unused)) + continue; + + _LOGT("obj[port:%s]: removed a port: %s%s%s", + key, + ovs_port->name, + NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid, + ", ", + ovs_port->connection_uuid, + "")); + _signal_emit_device_removed(self, ovs_port->name, NM_DEVICE_TYPE_OVS_PORT, NULL); + _free_port(ovs_port); + continue; } - if (new) { - ovs_port = g_slice_new(OpenvswitchPort); - ovs_port->name = g_strdup(name); - ovs_port->connection_uuid = _connection_uuid_from_external_ids(external_ids); - ovs_port->interfaces = g_ptr_array_new_with_free_func(g_free); - _uuids_to_array(ovs_port->interfaces, items); - g_hash_table_insert(priv->ports, g_strdup(key), ovs_port); - if (old) { - _LOGT("changed a port: %s%s%s", - ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - } else { - _LOGT("added a port: %s%s%s", + ovs_port = g_hash_table_lookup(priv->ports, &key); + + if (ovs_port && !nm_streq0(ovs_port->name, name)) { + if (!g_hash_table_steal(priv->ports, ovs_port)) + nm_assert_not_reached(); + _signal_emit_device_removed(self, ovs_port->name, NM_DEVICE_TYPE_OVS_PORT, NULL); + nm_clear_pointer(&ovs_port, _free_port); + } + + _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + interfaces = _uuids_to_array(items); + + if (ovs_port) { + gboolean changed = FALSE; + + nm_assert(nm_streq0(ovs_port->name, name)); + + changed |= nm_utils_strdup_reset(&ovs_port->name, name); + changed |= nm_utils_strdup_reset(&ovs_port->connection_uuid, connection_uuid); + if (nm_strv_ptrarray_cmp(ovs_port->interfaces, interfaces) != 0) { + NM_SWAP(&ovs_port->interfaces, &interfaces); + changed = TRUE; + } + if (!_external_ids_equal(ovs_port->external_ids, external_ids_arr)) { + NM_SWAP(&ovs_port->external_ids, &external_ids_arr); + changed = TRUE; + } + if (changed) { + gs_free char *strtmp = NULL; + + _LOGT("obj[port:%s]: changed a port: %s%s%s, external-ids=%s", + key, ovs_port->name, - ovs_port->connection_uuid ? ", " : "", - ovs_port->connection_uuid ?: ""); - g_signal_emit(self, - signals[DEVICE_ADDED], - 0, - ovs_port->name, - NM_DEVICE_TYPE_OVS_PORT); + NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid, + ", ", + ovs_port->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_port->external_ids))); } + } else { + gs_free char *strtmp = NULL; + + ovs_port = g_slice_new(OpenvswitchPort); + *ovs_port = (OpenvswitchPort){ + .port_uuid = g_strdup(key), + .name = g_strdup(name), + .connection_uuid = g_strdup(connection_uuid), + .interfaces = g_steal_pointer(&interfaces), + .external_ids = g_steal_pointer(&external_ids_arr), + }; + g_hash_table_add(priv->ports, ovs_port); + _LOGT("obj[port:%s]: added a port: %s%s%s, external-ids=%s", + key, + ovs_port->name, + NM_PRINT_FMT_QUOTED2(ovs_port->connection_uuid, + ", ", + ovs_port->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_port->external_ids))); + _signal_emit_device_added(self, ovs_port->name, NM_DEVICE_TYPE_OVS_PORT, NULL); } } - /* Bridges */ - json_object_foreach(bridge, key, value) - { - gboolean old = FALSE; - gboolean new = FALSE; - - if (json_unpack(value, "{s:{}}", "old") == 0) - old = TRUE; + json_object_foreach (bridge, key, value) { + gs_unref_ptrarray GPtrArray *ports = NULL; + OpenvswitchBridge * ovs_bridge; + gs_unref_array GArray *external_ids_arr = NULL; + const char * connection_uuid = NULL; + int r; - if (json_unpack(value, + r = json_unpack(value, "{s:{s:s, s:o, s:o}}", "new", "name", @@ -1369,50 +1837,93 @@ ovsdb_got_update(NMOvsdb *self, json_t *msg) "external_ids", &external_ids, "ports", - &items) - == 0) - new = TRUE; - - if (old) { - ovs_bridge = g_hash_table_lookup(priv->bridges, key); - if (!new || g_strcmp0(ovs_bridge->name, name) != 0) { - old = FALSE; - _LOGT("removed a bridge: %s%s%s", - ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - g_signal_emit(self, - signals[DEVICE_REMOVED], - 0, - ovs_bridge->name, - NM_DEVICE_TYPE_OVS_BRIDGE); - } - g_hash_table_remove(priv->bridges, key); + &items); + + if (r != 0) { + gpointer unused; + + r = json_unpack(value, "{s:{}}", "old"); + if (r != 0) + continue; + + if (!g_hash_table_steal_extended(priv->bridges, + &key, + (gpointer *) &ovs_bridge, + &unused)) + continue; + + _LOGT("obj[bridge:%s]: removed a bridge: %s%s%s", + key, + ovs_bridge->name, + NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid, + ", ", + ovs_bridge->connection_uuid, + "")); + _signal_emit_device_removed(self, ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE, NULL); + _free_bridge(ovs_bridge); + continue; } - if (new) { - ovs_bridge = g_slice_new(OpenvswitchBridge); - ovs_bridge->name = g_strdup(name); - ovs_bridge->connection_uuid = _connection_uuid_from_external_ids(external_ids); - ovs_bridge->ports = g_ptr_array_new_with_free_func(g_free); - _uuids_to_array(ovs_bridge->ports, items); - g_hash_table_insert(priv->bridges, g_strdup(key), ovs_bridge); - if (old) { - _LOGT("changed a bridge: %s%s%s", - ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - } else { - _LOGT("added a bridge: %s%s%s", + ovs_bridge = g_hash_table_lookup(priv->bridges, &key); + + if (ovs_bridge && !nm_streq0(ovs_bridge->name, name)) { + if (!g_hash_table_steal(priv->bridges, ovs_bridge)) + nm_assert_not_reached(); + _signal_emit_device_removed(self, ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE, NULL); + nm_clear_pointer(&ovs_bridge, _free_bridge); + } + + _external_ids_extract(external_ids, &external_ids_arr, &connection_uuid); + ports = _uuids_to_array(items); + + if (ovs_bridge) { + gboolean changed = FALSE; + + nm_assert(nm_streq0(ovs_bridge->name, name)); + + changed = nm_utils_strdup_reset(&ovs_bridge->name, name); + changed = nm_utils_strdup_reset(&ovs_bridge->connection_uuid, connection_uuid); + if (nm_strv_ptrarray_cmp(ovs_bridge->ports, ports) != 0) { + NM_SWAP(&ovs_bridge->ports, &ports); + changed = TRUE; + } + if (!_external_ids_equal(ovs_bridge->external_ids, external_ids_arr)) { + NM_SWAP(&ovs_bridge->external_ids, &external_ids_arr); + changed = TRUE; + } + if (changed) { + gs_free char *strtmp = NULL; + + _LOGT("obj[bridge:%s]: changed a bridge: %s%s%s, external-ids=%s", + key, ovs_bridge->name, - ovs_bridge->connection_uuid ? ", " : "", - ovs_bridge->connection_uuid ?: ""); - g_signal_emit(self, - signals[DEVICE_ADDED], - 0, - ovs_bridge->name, - NM_DEVICE_TYPE_OVS_BRIDGE); + NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid, + ", ", + ovs_bridge->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_bridge->external_ids))); } + } else { + gs_free char *strtmp = NULL; + + ovs_bridge = g_slice_new(OpenvswitchBridge); + *ovs_bridge = (OpenvswitchBridge){ + .bridge_uuid = g_strdup(key), + .name = g_strdup(name), + .connection_uuid = g_strdup(connection_uuid), + .ports = g_steal_pointer(&ports), + .external_ids = g_steal_pointer(&external_ids_arr), + }; + g_hash_table_add(priv->bridges, ovs_bridge); + _LOGT("obj[bridge:%s]: added a bridge: %s%s%s, external-ids=%s", + key, + ovs_bridge->name, + NM_PRINT_FMT_QUOTED2(ovs_bridge->connection_uuid, + ", ", + ovs_bridge->connection_uuid, + ""), + (strtmp = _external_ids_to_string(ovs_bridge->external_ids))); + _signal_emit_device_added(self, ovs_bridge->name, NM_DEVICE_TYPE_OVS_BRIDGE, NULL); } } } @@ -1455,16 +1966,12 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) json_error_t json_error = { 0, }; - json_t * json_id = NULL; - gint64 id = -1; - const char * method = NULL; - json_t * params = NULL; - json_t * result = NULL; - json_t * error = NULL; - OvsdbMethodCall * call = NULL; - OvsdbMethodCallback callback; - gpointer user_data; - gs_free_error GError *local = NULL; + json_t * json_id = NULL; + json_int_t id = (json_int_t) -1; + const char *method = NULL; + json_t * params = NULL; + json_t * result = NULL; + json_t * error = NULL; if (json_unpack_ex(msg, &json_error, @@ -1497,10 +2004,10 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) return; } - if (g_strcmp0(method, "update") == 0) { + if (nm_streq0(method, "update")) { /* This is a update method call. */ ovsdb_got_update(self, json_array_get(params, 1)); - } else if (g_strcmp0(method, "echo") == 0) { + } else if (nm_streq0(method, "echo")) { /* This is an echo request. */ ovsdb_got_echo(self, id, params); } else { @@ -1509,24 +2016,28 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) return; } - if (id > -1) { + if (id >= 0) { + OvsdbMethodCall *call; + gs_free_error GError *local = NULL; + gs_free char * msg_as_str = NULL; + /* This is a response to a method call. */ - if (!priv->calls->len) { - _LOGE("there are no queued calls expecting response %" G_GUINT64_FORMAT, id); + if (c_list_is_empty(&priv->calls_lst_head)) { + _LOGE("there are no queued calls expecting response %" G_GUINT64_FORMAT, (guint64) id); ovsdb_disconnect(self, FALSE, FALSE); return; } - call = &g_array_index(priv->calls, OvsdbMethodCall, 0); - if (call->id != id) { + call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst); + if (call->call_id != id) { _LOGE("expected a response to call %" G_GUINT64_FORMAT ", not %" G_GUINT64_FORMAT, - call->id, - id); + call->call_id, + (guint64) id); ovsdb_disconnect(self, FALSE, FALSE); return; } /* Cool, we found a corresponding call. Finish it. */ - _LOGT_call("response", call, msg); + _LOGT_call(call, "response: %s", (msg_as_str = json_dumps(msg, 0))); if (!json_is_null(error)) { /* The response contains an error. */ @@ -1537,10 +2048,8 @@ ovsdb_got_msg(NMOvsdb *self, json_t *msg) json_string_value(error)); } - callback = call->callback; - user_data = call->user_data; - g_array_remove_index(priv->calls, 0); - callback(self, result, local, user_data); + _call_complete(call, result, local); + priv->num_failures = 0; /* Don't progress further commands in case the callback hit an error @@ -1709,11 +2218,8 @@ ovsdb_write(NMOvsdb *self) static void ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) { - NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); - OvsdbMethodCall * call; - OvsdbMethodCallback callback; - gpointer user_data; - gs_free_error GError *error = NULL; + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + OvsdbMethodCall *call; nm_assert(!retry || !is_disposing); @@ -1722,19 +2228,23 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) _LOGD("disconnecting from ovsdb, retry %d", retry); + /* FIXME(shutdown): NMOvsdb should process the pending calls before + * shutting down, and cancel the remaining calls after the timeout. */ + if (retry) { - if (priv->calls->len != 0) - g_array_index(priv->calls, OvsdbMethodCall, 0).id = COMMAND_PENDING; - } else { - nm_utils_error_set_cancelled(&error, is_disposing, "NMOvsdb"); - - while (priv->calls->len) { - call = &g_array_index(priv->calls, OvsdbMethodCall, priv->calls->len - 1); - callback = call->callback; - user_data = call->user_data; - g_array_remove_index(priv->calls, priv->calls->len - 1); - callback(self, NULL, error, user_data); + if (!c_list_is_empty(&priv->calls_lst_head)) { + call = c_list_first_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst); + call->call_id = CALL_ID_UNSPEC; } + } else { + gs_free_error GError *error = NULL; + + if (is_disposing) + nm_utils_error_set_cancelled(&error, is_disposing, "NMOvsdb"); + else + nm_utils_error_set(&error, NM_UTILS_ERROR_NOT_READY, "disconnected from ovsdb"); + while ((call = c_list_last_entry(&priv->calls_lst_head, OvsdbMethodCall, calls_lst))) + _call_complete(call, NULL, error); } priv->bufp = 0; @@ -1750,6 +2260,76 @@ ovsdb_disconnect(NMOvsdb *self, gboolean retry, gboolean is_disposing) } static void +_check_ready(NMOvsdb *self) +{ + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + + nm_assert(!priv->ready); + + if (priv->num_pending_deletions == 0) { + priv->ready = TRUE; + g_signal_emit(self, signals[READY], 0); + nm_manager_unblock_failed_ovs_interfaces(nm_manager_get()); + } +} + +static void +_del_initial_iface_cb(GError *error, gpointer user_data) +{ + NMOvsdb * self; + gs_free char * ifname = NULL; + NMOvsdbPrivate *priv; + + nm_utils_user_data_unpack(user_data, &self, &ifname); + + if (nm_utils_error_is_cancelled_or_disposing(error)) + return; + + priv = NM_OVSDB_GET_PRIVATE(self); + nm_assert(priv->num_pending_deletions > 0); + priv->num_pending_deletions--; + + _LOGD("delete initial interface '%s': %s %s%s%s, pending %u", + ifname, + error ? "error" : "success", + error ? "(" : "", + error ? error->message : "", + error ? ")" : "", + priv->num_pending_deletions); + + _check_ready(self); +} + +static void +ovsdb_cleanup_initial_interfaces(NMOvsdb *self) +{ + NMOvsdbPrivate * priv = NM_OVSDB_GET_PRIVATE(self); + const OpenvswitchInterface *interface; + NMUtilsUserData * data; + GHashTableIter iter; + + if (priv->ready || priv->num_pending_deletions != 0) + return; + + /* Delete OVS interfaces added by NM. Bridges and ports and + * not considered because they are deleted automatically + * when no interface is present. */ + g_hash_table_iter_init(&iter, self->_priv.interfaces); + while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &interface)) { + if (interface->connection_uuid) { + priv->num_pending_deletions++; + _LOGD("deleting initial interface '%s' (pending: %u)", + interface->name, + priv->num_pending_deletions); + data = nm_utils_user_data_pack(self, g_strdup(interface->name)); + nm_ovsdb_del_interface(self, interface->name, _del_initial_iface_cb, data); + } + } + + _check_ready(self); +} + +static void _monitor_bridges_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) { if (error) { @@ -1763,6 +2343,8 @@ _monitor_bridges_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_ /* Treat the first response the same as the subsequent "update" * messages we eventually get. */ ovsdb_got_update(self, result); + + ovsdb_cleanup_initial_interfaces(self); } static void @@ -1823,17 +2405,11 @@ ovsdb_try_connect(NMOvsdb *self) /* Queue a monitor call before any other command, ensuring that we have an up * to date view of existing bridged that we need for add and remove ops. */ ovsdb_call_method(self, - OVSDB_MONITOR, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, _monitor_bridges_cb, NULL, - TRUE); + TRUE, + OVSDB_MONITOR, + OVSDB_METHOD_PAYLOAD_MONITOR()); } /*****************************************************************************/ @@ -1858,8 +2434,7 @@ _transact_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) if (error) goto out; - json_array_foreach(result, index, value) - { + json_array_foreach (result, index, value) { if (json_unpack(value, "{s:s, s:s}", "error", &err, "details", &err_details) == 0) { g_set_error(&error, G_IO_ERROR, @@ -1873,7 +2448,7 @@ _transact_cb(NMOvsdb *self, json_t *result, GError *error, gpointer user_data) out: call->callback(error, call->user_data); - g_slice_free(OvsdbCall, call); + nm_g_slice_free(call); } static OvsdbCall * @@ -1881,13 +2456,22 @@ ovsdb_call_new(NMOvsdbCallback callback, gpointer user_data) { OvsdbCall *call; - call = g_slice_new(OvsdbCall); - call->callback = callback; - call->user_data = user_data; - + call = g_slice_new(OvsdbCall); + *call = (OvsdbCall){ + .callback = callback, + .user_data = user_data, + }; return call; } +gboolean +nm_ovsdb_is_ready(NMOvsdb *self) +{ + NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); + + return priv->ready; +} + void nm_ovsdb_add_interface(NMOvsdb * self, NMConnection * bridge, @@ -1899,17 +2483,15 @@ nm_ovsdb_add_interface(NMOvsdb * self, gpointer user_data) { ovsdb_call_method(self, - OVSDB_ADD_INTERFACE, - NULL, - bridge, - port, - interface, - bridge_device, - interface_device, - 0, _transact_cb, ovsdb_call_new(callback, user_data), - FALSE); + FALSE, + OVSDB_ADD_INTERFACE, + OVSDB_METHOD_PAYLOAD_ADD_INTERFACE(bridge, + port, + interface, + bridge_device, + interface_device)); } void @@ -1919,17 +2501,11 @@ nm_ovsdb_del_interface(NMOvsdb * self, gpointer user_data) { ovsdb_call_method(self, - OVSDB_DEL_INTERFACE, - ifname, - NULL, - NULL, - NULL, - NULL, - NULL, - 0, _transact_cb, ovsdb_call_new(callback, user_data), - FALSE); + FALSE, + OVSDB_DEL_INTERFACE, + OVSDB_METHOD_PAYLOAD_DEL_INTERFACE(ifname)); } void @@ -1940,88 +2516,60 @@ nm_ovsdb_set_interface_mtu(NMOvsdb * self, gpointer user_data) { ovsdb_call_method(self, - OVSDB_SET_INTERFACE_MTU, - ifname, - NULL, - NULL, - NULL, - NULL, - NULL, - mtu, _transact_cb, ovsdb_call_new(callback, user_data), - FALSE); + FALSE, + OVSDB_SET_INTERFACE_MTU, + OVSDB_METHOD_PAYLOAD_SET_INTERFACE_MTU(ifname, mtu)); } -/*****************************************************************************/ - -static void -_clear_call(gpointer data) +void +nm_ovsdb_set_external_ids(NMOvsdb * self, + NMDeviceType device_type, + const char * ifname, + const char * connection_uuid, + NMSettingOvsExternalIDs *s_exid_old, + NMSettingOvsExternalIDs *s_exid_new) { - OvsdbMethodCall *call = data; - - switch (call->command) { - case OVSDB_MONITOR: - break; - case OVSDB_ADD_INTERFACE: - g_clear_object(&call->bridge); - g_clear_object(&call->port); - g_clear_object(&call->interface); - g_clear_object(&call->bridge_device); - g_clear_object(&call->interface_device); - break; - case OVSDB_DEL_INTERFACE: - case OVSDB_SET_INTERFACE_MTU: - nm_clear_g_free(&call->ifname); - break; - } -} + gs_unref_hashtable GHashTable *exid_old = NULL; + gs_unref_hashtable GHashTable *exid_new = NULL; -static void -_free_bridge(gpointer data) -{ - OpenvswitchBridge *ovs_bridge = data; + exid_old = s_exid_old + ? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_old)) + : NULL; + exid_new = s_exid_new + ? nm_utils_strdict_clone(_nm_setting_ovs_external_ids_get_data(s_exid_new)) + : NULL; - g_free(ovs_bridge->name); - g_free(ovs_bridge->connection_uuid); - g_ptr_array_free(ovs_bridge->ports, TRUE); - g_slice_free(OpenvswitchBridge, ovs_bridge); -} - -static void -_free_port(gpointer data) -{ - OpenvswitchPort *ovs_port = data; - - g_free(ovs_port->name); - g_free(ovs_port->connection_uuid); - g_ptr_array_free(ovs_port->interfaces, TRUE); - g_slice_free(OpenvswitchPort, ovs_port); + ovsdb_call_method(self, + NULL, + NULL, + FALSE, + OVSDB_SET_EXTERNAL_IDS, + OVSDB_METHOD_PAYLOAD_SET_EXTERNAL_IDS(device_type, + ifname, + connection_uuid, + exid_old, + exid_new)); } -static void -_free_interface(gpointer data) -{ - OpenvswitchInterface *ovs_interface = data; - - g_free(ovs_interface->name); - g_free(ovs_interface->connection_uuid); - g_free(ovs_interface->type); - g_slice_free(OpenvswitchInterface, ovs_interface); -} +/*****************************************************************************/ static void nm_ovsdb_init(NMOvsdb *self) { NMOvsdbPrivate *priv = NM_OVSDB_GET_PRIVATE(self); - priv->calls = g_array_new(FALSE, TRUE, sizeof(OvsdbMethodCall)); - g_array_set_clear_func(priv->calls, _clear_call); - priv->input = g_string_new(NULL); - priv->output = g_string_new(NULL); - priv->bridges = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_bridge); - priv->ports = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_port); - priv->interfaces = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, _free_interface); + c_list_init(&priv->calls_lst_head); + + priv->input = g_string_new(NULL); + priv->output = g_string_new(NULL); + priv->bridges = + g_hash_table_new_full(nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _free_bridge, NULL); + priv->ports = + g_hash_table_new_full(nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _free_port, NULL); + priv->interfaces = + g_hash_table_new_full(nm_pstr_hash, nm_pstr_equal, (GDestroyNotify) _free_interface, NULL); ovsdb_try_connect(self); } @@ -2034,6 +2582,8 @@ dispose(GObject *object) ovsdb_disconnect(self, FALSE, TRUE); + nm_assert(c_list_is_empty(&priv->calls_lst_head)); + if (priv->input) { g_string_free(priv->input, TRUE); priv->input = NULL; @@ -2042,10 +2592,6 @@ dispose(GObject *object) g_string_free(priv->output, TRUE); priv->output = NULL; } - if (priv->calls) { - g_array_free(priv->calls, TRUE); - priv->calls = NULL; - } nm_clear_pointer(&priv->bridges, g_hash_table_destroy); nm_clear_pointer(&priv->ports, g_hash_table_destroy); @@ -2069,9 +2615,10 @@ nm_ovsdb_class_init(NMOvsdbClass *klass) NULL, NULL, G_TYPE_NONE, - 2, + 3, G_TYPE_STRING, - G_TYPE_UINT); + G_TYPE_UINT, + G_TYPE_STRING); signals[DEVICE_REMOVED] = g_signal_new(NM_OVSDB_DEVICE_REMOVED, G_OBJECT_CLASS_TYPE(object_class), @@ -2081,9 +2628,10 @@ nm_ovsdb_class_init(NMOvsdbClass *klass) NULL, NULL, G_TYPE_NONE, - 2, + 3, G_TYPE_STRING, - G_TYPE_UINT); + G_TYPE_UINT, + G_TYPE_STRING); signals[INTERFACE_FAILED] = g_signal_new(NM_OVSDB_INTERFACE_FAILED, G_OBJECT_CLASS_TYPE(object_class), @@ -2097,4 +2645,14 @@ nm_ovsdb_class_init(NMOvsdbClass *klass) G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + signals[READY] = g_signal_new(NM_OVSDB_READY, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 0); } diff --git a/src/devices/ovs/nm-ovsdb.h b/src/core/devices/ovs/nm-ovsdb.h index c9eee19c..d0b4d19d 100644 --- a/src/devices/ovs/nm-ovsdb.h +++ b/src/core/devices/ovs/nm-ovsdb.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -16,6 +16,7 @@ #define NM_OVSDB_DEVICE_ADDED "device-added" #define NM_OVSDB_DEVICE_REMOVED "device-removed" #define NM_OVSDB_INTERFACE_FAILED "interface-failed" +#define NM_OVSDB_READY "ready" typedef struct _NMOvsdb NMOvsdb; typedef struct _NMOvsdbClass NMOvsdbClass; @@ -46,4 +47,15 @@ void nm_ovsdb_set_interface_mtu(NMOvsdb * self, NMOvsdbCallback callback, gpointer user_data); +struct _NMSettingOvsExternalIDs; + +void nm_ovsdb_set_external_ids(NMOvsdb * self, + NMDeviceType device_type, + const char * ifname, + const char * connection_uuid, + struct _NMSettingOvsExternalIDs *s_exid_old, + struct _NMSettingOvsExternalIDs *s_exid_new); + +gboolean nm_ovsdb_is_ready(NMOvsdb *self); + #endif /* __NETWORKMANAGER_OVSDB_H__ */ diff --git a/src/devices/team/meson.build b/src/core/devices/team/meson.build index c2b77cb9..d0ff4caa 100644 --- a/src/devices/team/meson.build +++ b/src/core/devices/team/meson.build @@ -1,20 +1,16 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nm-device-team.c', - 'nm-team-factory.c', -) - -deps = [ - daemon_nm_default_dep, - jansson_dep, - libteamdctl_dep, -] +# SPDX-License-Identifier: LGPL-2.1-or-later libnm_device_plugin_team = shared_module( 'nm-device-plugin-team', - sources: sources, - dependencies: deps, + sources: files( + 'nm-device-team.c', + 'nm-team-factory.c', + ), + dependencies: [ + core_plugin_dep, + jansson_dep, + libteamdctl_dep, + ], c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, @@ -27,5 +23,8 @@ core_plugins += libnm_device_plugin_team test( 'check-local-devices-team', check_exports, - args: [libnm_device_plugin_team.full_path(), linker_script_devices], + args: [ + libnm_device_plugin_team.full_path(), + linker_script_devices, + ], ) diff --git a/src/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 27aa3004..d2d71729 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us> * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-team.h" @@ -25,8 +25,8 @@ #include "nm-ip4-config.h" #include "nm-std-aux/nm-dbus-compat.h" +#define _NMLOG_DEVICE_TYPE NMDeviceTeam #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceTeam); /*****************************************************************************/ @@ -1003,18 +1003,18 @@ constructed(GObject *object) NMDevice * nm_device_team_new(const char *iface) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_TEAM, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_DRIVER, - "team", - NM_DEVICE_TYPE_DESC, - "Team", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_TEAM, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_TEAM, - NULL); + return g_object_new(NM_TYPE_DEVICE_TEAM, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_DRIVER, + "team", + NM_DEVICE_TYPE_DESC, + "Team", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_TEAM, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_TEAM, + NULL); } static void diff --git a/src/devices/team/nm-device-team.h b/src/core/devices/team/nm-device-team.h index eabc63e6..6f5cff93 100644 --- a/src/devices/team/nm-device-team.h +++ b/src/core/devices/team/nm-device-team.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Jiri Pirko <jiri@resnulli.us> */ diff --git a/src/devices/team/nm-team-factory.c b/src/core/devices/team/nm-team-factory.c index 644bef1c..57b51bf8 100644 --- a/src/devices/team/nm-team-factory.c +++ b/src/core/devices/team/nm-team-factory.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <gmodule.h> @@ -46,7 +46,7 @@ G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { nm_manager_set_capability(NM_MANAGER_GET, NM_CAPABILITY_TEAM); - return (NMDeviceFactory *) g_object_new(NM_TYPE_TEAM_FACTORY, NULL); + return g_object_new(NM_TYPE_TEAM_FACTORY, NULL); } /*****************************************************************************/ diff --git a/src/devices/tests/meson.build b/src/core/devices/tests/meson.build index 1ddd4f85..1bc88370 100644 --- a/src/devices/tests/meson.build +++ b/src/core/devices/tests/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_units = [ 'test-acd', @@ -9,7 +9,7 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/devices/tests/test-acd.c b/src/core/devices/tests/test-acd.c index da7b3c3d..b0af59db 100644 --- a/src/devices/tests/test-acd.c +++ b/src/core/devices/tests/test-acd.c @@ -1,12 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#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" diff --git a/src/devices/tests/test-lldp.c b/src/core/devices/tests/test-lldp.c index 5c912b7d..ef0b1549 100644 --- a/src/devices/tests/test-lldp.c +++ b/src/core/devices/tests/test-lldp.c @@ -1,11 +1,12 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <fcntl.h> +#include <netinet/if_ether.h> #include <linux/if_tun.h> #include <sys/ioctl.h> #include <sys/stat.h> @@ -811,17 +812,36 @@ _test_recv_fixture_setup(TestRecvFixture *fixture, gconstpointer user_data) link = nmtstp_assert_wait_for_link(NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 0); } else { int s; - struct ifreq ifr = {}; + struct ifreq ifr; + int r; + int try_cnt = 0; +again: + memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; nm_utils_ifname_cpy(ifr.ifr_name, TEST_IFNAME); - g_assert(ioctl(fd, TUNSETIFF, &ifr) >= 0); + + r = ioctl(fd, TUNSETIFF, &ifr); + if (r != 0) { + if (errno == EPERM && try_cnt++ < 10) { + g_usleep(2); + goto again; + } + g_assert_cmpint(errno, ==, 0); + g_assert_cmpint(r, ==, 0); + } /* Bring the interface up */ s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); g_assert(s >= 0); + ifr.ifr_flags |= IFF_UP; - g_assert(ioctl(s, SIOCSIFFLAGS, &ifr) >= 0); + r = ioctl(s, SIOCSIFFLAGS, &ifr); + if (r != 0) { + g_assert_cmpint(errno, ==, 0); + g_assert_cmpint(r, ==, 0); + } + nm_close(s); link = nmtstp_assert_wait_for_link(NM_PLATFORM_GET, TEST_IFNAME, NM_LINK_TYPE_TUN, 100); diff --git a/src/devices/wifi/meson.build b/src/core/devices/wifi/meson.build index 00404c71..743937db 100644 --- a/src/devices/wifi/meson.build +++ b/src/core/devices/wifi/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later iwd_sources = files() if enable_iwd @@ -8,8 +8,8 @@ if enable_iwd ) endif -libnm_wifi_base = static_library( - 'nm-wifi-base', +libnm_device_plugin_wifi_static = static_library( + 'nm-device-plugin-wifi-static', sources: files( 'nm-device-olpc-mesh.c', 'nm-device-wifi-p2p.c', @@ -19,12 +19,14 @@ libnm_wifi_base = static_library( 'nm-wifi-p2p-peer.c', 'nm-wifi-utils.c', ) + iwd_sources, - dependencies: daemon_nm_default_dep, + dependencies: [ + core_plugin_dep, + ], c_args: daemon_c_flags, ) -libnm_wifi_base_dep = declare_dependency( - link_with: libnm_wifi_base, +libnm_device_plugin_wifi_static_dep = declare_dependency( + link_with: libnm_device_plugin_wifi_static, ) libnm_device_plugin_wifi = shared_module( @@ -32,7 +34,10 @@ libnm_device_plugin_wifi = shared_module( sources: files( 'nm-wifi-factory.c', ), - dependencies: [ daemon_nm_default_dep, libnm_wifi_base_dep ], + dependencies: [ + core_plugin_dep, + libnm_device_plugin_wifi_static_dep + ], c_args: daemon_c_flags, link_args: ldflags_linker_script_devices, link_depends: linker_script_devices, @@ -54,7 +59,10 @@ if enable_tests exe = executable( test_unit, 'tests/' + test_unit + '.c', - dependencies: [ libnetwork_manager_test_dep, libnm_wifi_base_dep ], + dependencies: [ + libNetworkManagerTest_dep, + libnm_device_plugin_wifi_static_dep, + ], c_args: test_c_flags, ) diff --git a/src/devices/wifi/nm-device-iwd.c b/src/core/devices/wifi/nm-device-iwd.c index 64ac3de7..f0de90d3 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/core/devices/wifi/nm-device-iwd.c @@ -1,12 +1,14 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Intel Corporation */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-iwd.h" +#include <linux/if_ether.h> + #include "devices/nm-device-private.h" #include "devices/nm-device.h" #include "nm-act-request.h" @@ -27,9 +29,11 @@ #include "settings/nm-settings-connection.h" #include "settings/nm-settings.h" #include "supplicant/nm-supplicant-types.h" +#include "nm-auth-utils.h" +#include "nm-manager.h" +#define _NMLOG_DEVICE_TYPE NMDeviceIwd #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceIwd); /*****************************************************************************/ @@ -54,13 +58,24 @@ typedef struct { NMDeviceWifiCapabilities capabilities; NMActRequestGetSecretsCallId *wifi_secrets_id; guint periodic_scan_id; + guint periodic_update_id; bool enabled : 1; bool can_scan : 1; - bool can_connect : 1; + bool nm_autoconnect : 1; + bool iwd_autoconnect : 1; bool scanning : 1; bool scan_requested : 1; bool act_mode_switch : 1; + bool secrets_failed : 1; + bool networks_requested : 1; + bool networks_changed : 1; gint64 last_scan; + uint32_t ap_id; + guint32 rate; + NMEtherAddr current_ap_bssid; + GDBusMethodInvocation * pending_agent_request; + NMActiveConnection * assumed_ac; + guint assumed_ac_timeout; } NMDeviceIwdPrivate; struct _NMDeviceIwd { @@ -129,7 +144,9 @@ ap_add_remove(NMDeviceIwd *self, nm_dbus_object_clear_and_unexport(&ap); } - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + if (priv->enabled && !priv->iwd_autoconnect) + nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + if (recheck_available_connections) nm_device_recheck_available_connections(NM_DEVICE(self)); } @@ -159,6 +176,7 @@ set_current_ap(NMDeviceIwd *self, NMWifiAP *new_ap, gboolean recheck_available_c g_object_unref(old_ap); } + memset(&priv->current_ap_bssid, 0, ETH_ALEN); _notify(self, PROP_ACTIVE_ACCESS_POINT); _notify(self, PROP_MODE); } @@ -172,12 +190,12 @@ remove_all_aps(NMDeviceIwd *self) if (c_list_is_empty(&priv->aps_lst_head)) return; - set_current_ap(self, NULL, FALSE); - c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) ap_add_remove(self, FALSE, ap, FALSE); - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + if (!priv->iwd_autoconnect) + nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_available_connections(NM_DEVICE(self)); } @@ -198,49 +216,37 @@ ap_security_flags_from_network_type(const char *type) return flags; } -static void -insert_ap_from_network(NMDeviceIwd *self, - GHashTable * aps, - const char * path, - gint64 last_seen_msec, - int16_t signal, - uint32_t ap_id) +static NMWifiAP * +ap_from_network(NMDeviceIwd *self, + GDBusProxy * network, + NMRefString *bss_path, + gint64 last_seen_msec, + int16_t signal) { - gs_unref_object GDBusProxy *network_proxy = NULL; - gs_unref_variant GVariant *name_value = NULL; - gs_unref_variant GVariant *type_value = NULL; - nm_auto_ref_string NMRefString *bss_path = NULL; - const char * name; - const char * type; - NMSupplicantBssInfo bss_info; - uint8_t bssid[6]; - NMWifiAP * ap; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + gs_unref_variant GVariant *name_value = NULL; + gs_unref_variant GVariant *type_value = NULL; + const char * name; + const char * type; + uint32_t ap_id; gs_unref_bytes GBytes *ssid = NULL; + NMWifiAP * ap; + NMSupplicantBssInfo bss_info; - bss_path = nm_ref_string_new(path); - - if (g_hash_table_lookup(aps, path)) { - _LOGD(LOGD_WIFI, "Duplicate network at %s", path); - return; - } - - network_proxy = - nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), path, NM_IWD_NETWORK_INTERFACE); - if (!network_proxy) - return; + g_return_val_if_fail(network, NULL); - name_value = g_dbus_proxy_get_cached_property(network_proxy, "Name"); - type_value = g_dbus_proxy_get_cached_property(network_proxy, "Type"); + name_value = g_dbus_proxy_get_cached_property(network, "Name"); + type_value = g_dbus_proxy_get_cached_property(network, "Type"); if (!name_value || !g_variant_is_of_type(name_value, G_VARIANT_TYPE_STRING) || !type_value || !g_variant_is_of_type(type_value, G_VARIANT_TYPE_STRING)) - return; + return NULL; name = g_variant_get_string(name_value, NULL); type = g_variant_get_string(type_value, NULL); if (nm_streq(type, "wep")) { /* WEP not supported */ - return; + return NULL; } /* What we get from IWD are networks, or ESSs, that may contain @@ -251,12 +257,7 @@ insert_ap_from_network(NMDeviceIwd *self, * already does that. We fake the BSSIDs as they don't play any * role either. */ - bssid[0] = 0x00; - bssid[1] = 0x01; - bssid[2] = 0x02; - bssid[3] = ap_id >> 16; - bssid[4] = ap_id >> 8; - bssid[5] = ap_id; + ap_id = priv->ap_id++; ssid = g_bytes_new(name, NM_MIN(32u, strlen(name))); @@ -270,13 +271,39 @@ insert_ap_from_network(NMDeviceIwd *self, .signal_percent = nm_wifi_utils_level_to_quality(signal / 100), .frequency = 2417, .max_rate = 65000, + .bssid = NM_ETHER_ADDR_INIT(0x00, 0x01, 0x02, ap_id >> 16, ap_id >> 8, ap_id), }; - memcpy(bss_info.bssid, bssid, sizeof(bssid)); ap = nm_wifi_ap_new_from_properties(&bss_info); nm_assert(bss_path == nm_wifi_ap_get_supplicant_path(ap)); + return ap; +} + +static void +insert_ap_from_network(NMDeviceIwd *self, + GHashTable * aps, + const char * path, + gint64 last_seen_msec, + int16_t signal) +{ + gs_unref_object GDBusProxy *network_proxy = NULL; + nm_auto_ref_string NMRefString *bss_path = nm_ref_string_new(path); + NMWifiAP * ap; + + if (g_hash_table_lookup(aps, bss_path)) { + _LOGD(LOGD_WIFI, "Duplicate network at %s", path); + return; + } + + network_proxy = + nm_iwd_manager_get_dbus_interface(nm_iwd_manager_get(), path, NM_IWD_NETWORK_INTERFACE); + + ap = ap_from_network(self, network_proxy, bss_path, last_seen_msec, signal); + if (!ap) + return; + g_hash_table_insert(aps, bss_path, ap); } @@ -288,55 +315,45 @@ get_ordered_networks_cb(GObject *source, GAsyncResult *res, gpointer user_data) gs_free_error GError *error = NULL; gs_unref_variant GVariant *variant = NULL; GVariantIter * networks; - const char * path, *name, *type; + const char * path; int16_t signal; NMWifiAP * ap, *ap_safe, *new_ap; - gboolean changed = FALSE; + gboolean changed; GHashTableIter ap_iter; gs_unref_hashtable GHashTable *new_aps = NULL; - gboolean compat; - const char * return_sig; - static uint32_t ap_id = 0; gint64 last_seen_msec; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!variant && nm_utils_error_is_cancelled(error)) + return; + + priv = NM_DEVICE_IWD_GET_PRIVATE(self); + priv->networks_requested = FALSE; + if (!variant) { _LOGE(LOGD_WIFI, "Station.GetOrderedNetworks failed: %s", error->message); return; } - priv = NM_DEVICE_IWD_GET_PRIVATE(self); - - /* Depending on whether we're using the Station interface or the Device - * interface for compatibility with IWD <= 0.7, the return signature of - * GetOrderedNetworks will be different. - */ - compat = priv->dbus_station_proxy == priv->dbus_device_proxy; - return_sig = compat ? "(a(osns))" : "(a(on))"; - - if (!g_variant_is_of_type(variant, G_VARIANT_TYPE(return_sig))) { + if (!g_variant_is_of_type(variant, G_VARIANT_TYPE("(a(on))"))) { _LOGE(LOGD_WIFI, - "Station.GetOrderedNetworks returned type %s instead of %s", - g_variant_get_type_string(variant), - return_sig); + "Station.GetOrderedNetworks returned type %s instead of (a(on))", + g_variant_get_type_string(variant)); return; } new_aps = g_hash_table_new_full(nm_direct_hash, NULL, NULL, g_object_unref); - - g_variant_get(variant, return_sig, &networks); + g_variant_get(variant, "(a(on))", &networks); last_seen_msec = nm_utils_get_monotonic_timestamp_msec(); - if (compat) { - while (g_variant_iter_next(networks, "(&o&sn&s)", &path, &name, &signal, &type)) - insert_ap_from_network(self, new_aps, path, last_seen_msec, signal, ap_id++); - } else { - while (g_variant_iter_next(networks, "(&on)", &path, &signal)) - insert_ap_from_network(self, new_aps, path, last_seen_msec, signal, ap_id++); - } + while (g_variant_iter_next(networks, "(&on)", &path, &signal)) + insert_ap_from_network(self, new_aps, path, last_seen_msec, signal); g_variant_iter_free(networks); + changed = priv->networks_changed; + priv->networks_changed = FALSE; + c_list_for_each_entry_safe (ap, ap_safe, &priv->aps_lst_head, aps_lst) { new_ap = g_hash_table_lookup(new_aps, nm_wifi_ap_get_supplicant_path(ap)); if (new_ap) { @@ -368,7 +385,9 @@ get_ordered_networks_cb(GObject *source, GAsyncResult *res, gpointer user_data) } if (changed) { - nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + if (!priv->iwd_autoconnect) + nm_device_emit_recheck_auto_activate(NM_DEVICE(self)); + nm_device_recheck_available_connections(NM_DEVICE(self)); } } @@ -389,6 +408,61 @@ update_aps(NMDeviceIwd *self) priv->cancellable, get_ordered_networks_cb, self); + priv->networks_requested = TRUE; +} + +static void +periodic_update(NMDeviceIwd *self) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + int ifindex; + guint32 new_rate; + int percent; + NMEtherAddr bssid; + gboolean ap_changed = FALSE; + NMPlatform * platform; + + ifindex = nm_device_get_ifindex(NM_DEVICE(self)); + if (ifindex <= 0) + g_return_if_reached(); + + platform = nm_device_get_platform(NM_DEVICE(self)); + + /* TODO: obtain quality through the net.connman.iwd.SignalLevelAgent API. + * For now we're waking up for the rate/BSSID updates anyway. + */ + if (!nm_platform_wifi_get_station(platform, ifindex, &bssid, &percent, &new_rate)) { + _LOGD(LOGD_WIFI, "BSSID / quality / rate platform query failed"); + return; + } + + if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { +#if NM_MORE_LOGGING + ap_changed = TRUE; +#endif + } + + if (new_rate != priv->rate) { + priv->rate = new_rate; + _notify(self, PROP_BITRATE); + } + + if (nm_ether_addr_is_valid(&bssid) && !nm_ether_addr_equal(&bssid, &priv->current_ap_bssid)) { + priv->current_ap_bssid = bssid; + ap_changed |= nm_wifi_ap_set_address_bin(priv->current_ap, &bssid); + ap_changed |= nm_wifi_ap_set_freq(priv->current_ap, + nm_platform_wifi_get_frequency(platform, ifindex)); + } + + if (ap_changed) + _ap_dump(self, LOGL_DEBUG, priv->current_ap, "updated"); +} + +static gboolean +periodic_update_cb(gpointer user_data) +{ + periodic_update(user_data); + return TRUE; } static void @@ -414,6 +488,26 @@ wifi_secrets_cancel(NMDeviceIwd *self) if (priv->wifi_secrets_id) nm_act_request_cancel_secrets(NULL, priv->wifi_secrets_id); nm_assert(!priv->wifi_secrets_id); + + if (priv->pending_agent_request) { + g_dbus_method_invocation_return_error_literal(priv->pending_agent_request, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "NM secrets request cancelled"); + g_clear_object(&priv->pending_agent_request); + } +} + +static void +cleanup_assumed_connect(NMDeviceIwd *self) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + + if (!priv->assumed_ac) + return; + + g_signal_handlers_disconnect_by_data(priv->assumed_ac, self); + g_clear_object(&priv->assumed_ac); } static void @@ -421,9 +515,12 @@ cleanup_association_attempt(NMDeviceIwd *self, gboolean disconnect) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + cleanup_assumed_connect(self); wifi_secrets_cancel(self); set_current_ap(self, NULL, TRUE); + nm_clear_g_source(&priv->periodic_update_id); + nm_clear_g_source(&priv->assumed_ac_timeout); if (disconnect && priv->dbus_station_proxy) send_disconnect(self); @@ -448,6 +545,32 @@ reset_mode(NMDeviceIwd * self, user_data); } +static gboolean +get_variant_boolean(GVariant *v, const char *property) +{ + if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { + nm_log_warn(LOGD_DEVICE | LOGD_WIFI, + "Property %s not cached or not boolean type", + property); + + return FALSE; + } + + return g_variant_get_boolean(v); +} + +static const char * +get_variant_state(GVariant *v) +{ + if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_STRING)) { + nm_log_warn(LOGD_DEVICE | LOGD_WIFI, "State property not cached or not a string"); + + return "unknown"; + } + + return g_variant_get_string(v, NULL); +} + static void deactivate(NMDevice *device) { @@ -457,6 +580,14 @@ deactivate(NMDevice *device) if (!priv->dbus_obj) return; + if (priv->dbus_station_proxy) { + gs_unref_variant GVariant *value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + + if (NM_IN_STRSET(get_variant_state(value), "disconnecting", "disconnected")) + return; + } + cleanup_association_attempt(self, TRUE); priv->act_mode_switch = FALSE; @@ -532,27 +663,13 @@ deactivate_async(NMDevice * device, static gboolean is_connection_known_network(NMConnection *connection) { - NMSettingWireless * s_wireless; NMIwdNetworkSecurity security; - gboolean security_ok; - GBytes * ssid; - gs_free char * ssid_utf8 = NULL; - - s_wireless = nm_connection_get_setting_wireless(connection); - if (!s_wireless) - return FALSE; + gs_free char * ssid = NULL; - ssid = nm_setting_wireless_get_ssid(s_wireless); - if (!ssid) + if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, &security)) return FALSE; - ssid_utf8 = _nm_utils_ssid_to_utf8(ssid); - - security = nm_wifi_connection_get_iwd_security(connection, &security_ok); - if (!security_ok) - return FALSE; - - return nm_iwd_manager_is_known_network(nm_iwd_manager_get(), ssid_utf8, security); + return nm_iwd_manager_is_known_network(nm_iwd_manager_get(), ssid, security); } static gboolean @@ -584,7 +701,9 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * const char * perm_hw_addr; const char * mode; NMIwdNetworkSecurity security; - gboolean mapped; + GBytes * ssid; + const guint8 * ssid_bytes; + gsize ssid_len; if (!NM_DEVICE_CLASS(nm_device_iwd_parent_class) ->check_connection_compatible(device, connection, error)) @@ -592,12 +711,29 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * s_wireless = nm_connection_get_setting_wireless(connection); + /* complete_connection would be called (if at all) before this function + * so an SSID should always be set. IWD doesn't support non-UTF8 SSIDs + * (ignores BSSes with such SSIDs and has no way to represent them on + * DBus) so we can cut it short for connections with a non-UTF8 SSID. + */ + ssid = nm_setting_wireless_get_ssid(s_wireless); + if (!ssid) + return FALSE; + + ssid_bytes = g_bytes_get_data(ssid, &ssid_len); + if (!g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "non-UTF-8 connection SSID not supported by IWD backend"); + return FALSE; + } + perm_hw_addr = nm_device_get_permanent_hw_address(device); mac = nm_setting_wireless_get_mac_address(s_wireless); if (perm_hw_addr) { if (mac && !nm_utils_hwaddr_matches(mac, -1, perm_hw_addr, -1)) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device MAC address does not match the profile"); return FALSE; } @@ -621,10 +757,10 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * return FALSE; } - security = nm_wifi_connection_get_iwd_security(connection, &mapped); - if (!mapped) { + if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security) + || security == NM_IWD_NETWORK_SECURITY_WEP) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "connection authentication type not supported by IWD backend"); return FALSE; } @@ -636,7 +772,7 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * && !NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) { nm_utils_error_set_literal( error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "non-infrastructure hidden networks not supported by the IWD backend"); return FALSE; } @@ -648,52 +784,63 @@ check_connection_compatible(NMDevice *device, NMConnection *connection, GError * if (security == NM_IWD_NETWORK_SECURITY_8021X) { if (!is_connection_known_network(connection)) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "802.1x connections must have IWD provisioning files"); return FALSE; } } else if (!NM_IN_SET(security, - NM_IWD_NETWORK_SECURITY_NONE, + NM_IWD_NETWORK_SECURITY_OPEN, NM_IWD_NETWORK_SECURITY_PSK)) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "IWD backend only supports Open, PSK and 802.1x network " "authentication in Infrastructure mode"); return FALSE; } } else if (nm_streq(mode, NM_SETTING_WIRELESS_MODE_AP)) { + NMSettingWirelessSecurity *s_wireless_sec = + nm_connection_get_setting_wireless_security(connection); + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_AP)) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device does not support Access Point mode"); return FALSE; } - if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_PSK)) { + if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_PSK) || !s_wireless_sec + || !nm_streq0(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), "wpa-psk")) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "IWD backend only supports PSK authentication in AP mode"); return FALSE; } } else if (nm_streq(mode, NM_SETTING_WIRELESS_MODE_ADHOC)) { + NMSettingWirelessSecurity *s_wireless_sec = + nm_connection_get_setting_wireless_security(connection); + if (!(priv->capabilities & NM_WIFI_DEVICE_CAP_ADHOC)) { nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "device does not support Ad-Hoc mode"); return FALSE; } - if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_NONE, NM_IWD_NETWORK_SECURITY_PSK)) { + if (!NM_IN_SET(security, NM_IWD_NETWORK_SECURITY_OPEN, NM_IWD_NETWORK_SECURITY_PSK) + || (s_wireless_sec + && !nm_streq0(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), + "wpa-psk"))) { nm_utils_error_set_literal( error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, "IWD backend only supports Open and PSK authentication in Ad-Hoc mode"); return FALSE; } } else { - nm_utils_error_set_literal(error, - NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY, - "%s type profiles not supported by IWD backend"); + nm_utils_error_set(error, + NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE, + "'%s' type profiles not supported by IWD backend", + mode); return FALSE; } @@ -707,11 +854,12 @@ check_connection_available(NMDevice * device, const char * specific_object, GError ** error) { - NMDeviceIwd * self = NM_DEVICE_IWD(device); - NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMSettingWireless * s_wifi; - const char * mode; - NMWifiAP * ap = NULL; + NMDeviceIwd * self = NM_DEVICE_IWD(device); + NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingWireless * s_wifi; + const char * mode; + NMWifiAP * ap = NULL; + NMIwdNetworkSecurity security; s_wifi = nm_connection_get_setting_wireless(connection); g_return_val_if_fail(s_wifi, FALSE); @@ -740,7 +888,16 @@ check_connection_available(NMDevice * device, if (NM_IN_STRSET(mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC)) return TRUE; - if (NM_FLAGS_HAS(flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP)) + /* Hidden SSIDs obviously don't always appear in the scan list either. + * + * For an explicit user-activation-request, a connection is considered + * available because for hidden Wi-Fi, clients didn't consistently + * set the 'hidden' property to indicate hidden SSID networks. If + * activating but the network isn't available let the device recheck + * availability. + */ + if (nm_setting_wireless_get_hidden(s_wifi) + || NM_FLAGS_HAS(flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP)) return TRUE; if (!ap) @@ -756,7 +913,8 @@ check_connection_available(NMDevice * device, /* 8021x networks can only be used if they've been provisioned on the IWD side and * thus are Known Networks. */ - if (nm_wifi_connection_get_iwd_security(connection, NULL) == NM_IWD_NETWORK_SECURITY_8021X) { + if (nm_wifi_connection_get_iwd_ssid_and_security(connection, NULL, &security) + && security == NM_IWD_NETWORK_SECURITY_8021X) { if (!is_ap_known_network(ap)) { nm_utils_error_set_literal( error, @@ -769,6 +927,18 @@ check_connection_available(NMDevice * device, return TRUE; } +/* To be used where the SSID has been validated before */ +static char * +iwd_ssid_to_str(const GBytes *ssid) +{ + const guint8 *ssid_bytes; + gsize ssid_len; + + ssid_bytes = g_bytes_get_data((GBytes *) ssid, &ssid_len); + nm_assert(ssid && g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)); + return g_strndup((const char *) ssid_bytes, ssid_len); +} + static gboolean complete_connection(NMDevice * device, NMConnection * connection, @@ -781,20 +951,18 @@ complete_connection(NMDevice * device, NMSettingWireless * s_wifi; gs_free char * ssid_utf8 = NULL; NMWifiAP * ap; - GBytes * ssid; - GBytes * setting_ssid = NULL; - gboolean hidden = FALSE; + GBytes * ssid = NULL; + gboolean hidden = FALSE; const char * mode; s_wifi = nm_connection_get_setting_wireless(connection); mode = s_wifi ? nm_setting_wireless_get_mode(s_wifi) : NULL; - if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) { - if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error)) - return FALSE; - ap = NULL; - } else if (!specific_object) { + if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP) || !specific_object) { + const guint8 *ssid_bytes; + gsize ssid_len; + /* If not given a specific object, we need at minimum an SSID */ if (!s_wifi) { g_set_error_literal(error, @@ -804,16 +972,24 @@ complete_connection(NMDevice * device, return FALSE; } - setting_ssid = nm_setting_wireless_get_ssid(s_wifi); - if (!setting_ssid || g_bytes_get_size(setting_ssid) == 0) { - g_set_error_literal( - error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required if no AP path was given."); + ssid = nm_setting_wireless_get_ssid(s_wifi); + ssid_bytes = g_bytes_get_data(ssid, &ssid_len); + + if (!ssid || ssid_len == 0 || !g_utf8_validate((const char *) ssid_bytes, ssid_len, NULL)) { + g_set_error_literal(error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'wireless' setting with a valid UTF-8 SSID is required if no AP " + "path was given."); return FALSE; } + } + if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) { + if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error)) + return FALSE; + ap = NULL; + } else if (!specific_object) { /* Find a compatible AP in the scan list */ ap = nm_wifi_aps_find_first_compatible(&priv->aps_lst_head, connection); if (!ap) { @@ -824,6 +1000,12 @@ complete_connection(NMDevice * device, if (!nm_setting_verify(NM_SETTING(s_wifi), connection, error)) return FALSE; + /* We could either require the profile to be marked as hidden by the + * client or at least check that a hidden AP with a matching security + * type is in range using Station.GetHiddenAccessPoints(). For now + * assume it is hidden even though that will reveal the SSID on the + * air. + */ hidden = TRUE; } } else { @@ -836,35 +1018,22 @@ complete_connection(NMDevice * device, specific_object); return FALSE; } - } - /* Add a wifi setting if one doesn't exist yet */ - if (!s_wifi) { - s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); - nm_connection_add_setting(connection, NM_SETTING(s_wifi)); - } - - ssid = nm_setting_wireless_get_ssid(s_wifi); - if (!ssid && ap) ssid = nm_wifi_ap_get_ssid(ap); - if (!ssid) { - g_set_error_literal(error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wireless' setting with a valid SSID is required."); - return FALSE; + /* Add a wifi setting if one doesn't exist yet */ + if (!s_wifi) { + s_wifi = (NMSettingWireless *) nm_setting_wireless_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wifi)); + } } if (ap) { - if (!nm_wifi_ap_complete_connection(ap, - connection, - nm_wifi_utils_is_manf_default_ssid(ssid), - error)) + if (!nm_wifi_ap_complete_connection(ap, connection, FALSE, error)) return FALSE; } - ssid_utf8 = _nm_utils_ssid_to_utf8(ssid); + ssid_utf8 = iwd_ssid_to_str(ssid); nm_utils_complete_generic( nm_device_get_platform(device), connection, @@ -883,32 +1052,6 @@ complete_connection(NMDevice * device, } static gboolean -get_variant_boolean(GVariant *v, const char *property) -{ - if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) { - nm_log_warn(LOGD_DEVICE | LOGD_WIFI, - "Property %s not cached or not boolean type", - property); - - return FALSE; - } - - return g_variant_get_boolean(v); -} - -static const char * -get_variant_state(GVariant *v) -{ - if (!v || !g_variant_is_of_type(v, G_VARIANT_TYPE_STRING)) { - nm_log_warn(LOGD_DEVICE | LOGD_WIFI, "State property not cached or not a string"); - - return "unknown"; - } - - return g_variant_get_string(v, NULL); -} - -static gboolean is_available(NMDevice *device, NMDeviceCheckDevAvailableFlags flags) { NMDeviceIwd * self = NM_DEVICE_IWD(device); @@ -934,7 +1077,7 @@ get_autoconnect_allowed(NMDevice *device) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(NM_DEVICE_IWD(device)); - return priv->can_connect; + return priv->nm_autoconnect; } static gboolean @@ -1114,7 +1257,6 @@ check_scanning_prohibited(NMDeviceIwd *self, gboolean periodic) case NM_DEVICE_STATE_UNAVAILABLE: case NM_DEVICE_STATE_PREPARE: case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: case NM_DEVICE_STATE_IP_CONFIG: case NM_DEVICE_STATE_IP_CHECK: case NM_DEVICE_STATE_SECONDARIES: @@ -1124,6 +1266,7 @@ check_scanning_prohibited(NMDeviceIwd *self, gboolean periodic) case NM_DEVICE_STATE_DISCONNECTED: case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_ACTIVATED: + case NM_DEVICE_STATE_NEED_AUTH: break; } @@ -1131,6 +1274,27 @@ check_scanning_prohibited(NMDeviceIwd *self, gboolean periodic) return !priv->can_scan; } +static const char * +get_agent_request_network_path(GDBusMethodInvocation *invocation) +{ + const char *method_name = g_dbus_method_invocation_get_method_name(invocation); + GVariant * params = g_dbus_method_invocation_get_parameters(invocation); + const char *network_path = NULL; + + if (nm_streq(method_name, "RequestPassphrase")) + g_variant_get(params, "(o)", &network_path); + else if (nm_streq(method_name, "RequestPrivateKeyPassphrase")) + g_variant_get(params, "(o)", &network_path); + else if (nm_streq(method_name, "RequestUserNameAndPassword")) + g_variant_get(params, "(o)", &network_path); + else if (nm_streq(method_name, "RequestUserPassword")) { + const char *user; + g_variant_get(params, "(os)", &network_path, &user); + } + + return network_path; +} + /* * try_reply_agent_request * @@ -1238,6 +1402,25 @@ try_reply_agent_request(NMDeviceIwd * self, return FALSE; } +static gboolean +assumed_ac_timeout_cb(gpointer user_data) +{ + NMDeviceIwd * self = user_data; + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + + nm_assert(priv->assumed_ac); + + priv->assumed_ac_timeout = 0; + nm_device_state_changed(NM_DEVICE(self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + /* NMDevice's state change -> NMActRequests/NMActiveConnection's state + * change -> assumed_connection_state_changed_before_managed() -> + * cleanup_association_attempt() so no need to call it explicitly. + */ + return G_SOURCE_REMOVE; +} + static void wifi_secrets_get_one(NMDeviceIwd * self, const char * setting_name, NMSecretAgentGetSecretsFlags flags, @@ -1273,6 +1456,7 @@ wifi_secrets_cb(NMActRequest * req, priv->wifi_secrets_id = NULL; if (nm_utils_error_is_cancelled(error)) { + priv->secrets_failed = TRUE; g_dbus_method_invocation_return_error_literal(invocation, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, @@ -1300,6 +1484,20 @@ wifi_secrets_cb(NMActRequest * req, goto secrets_error; if (replied) { + /* If we replied to the secrets request from IWD in the "disconnected" + * state and IWD doesn't move to a new state within 1 second, assume + * something went wrong (shouldn't happen). If a state change arrives + * after that nothing is lost, state_changed() will try to assume the + * connection again. + */ + if (priv->assumed_ac) { + gs_unref_variant GVariant *value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + + if (nm_streq(get_variant_state(value), "disconnected")) + priv->assumed_ac_timeout = g_timeout_add_seconds(1, assumed_ac_timeout_cb, self); + } + /* Change state back to what it was before NEED_AUTH */ nm_device_state_changed(device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); return; @@ -1317,7 +1515,17 @@ secrets_error: NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, "NM secrets request failed"); - /* Now wait for the Connect callback to update device state */ + + if (priv->assumed_ac) { + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_NO_SECRETS); + /* NMDevice's state change -> NMActRequests/NMActiveConnection's state + * change -> assumed_connection_state_changed_before_managed() -> + * cleanup_association_attempt() so no need to call it explicitly. + */ + } else { + priv->secrets_failed = TRUE; + /* Now wait for the Connect callback to update device state */ + } } static void @@ -1353,11 +1561,13 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) gs_unref_variant GVariant *variant = NULL; gs_free_error GError *error = NULL; NMConnection * connection; - NMSettingWireless * s_wifi; - GBytes * ssid; - gs_free char * ssid_utf8 = NULL; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; + gs_free char * ssid = NULL; + NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED; GVariant * value; + gboolean disconnect; + + disconnect = !priv->iwd_autoconnect + || nm_device_autoconnect_blocked_get(device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL); variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { @@ -1391,7 +1601,7 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) /* If secrets were wrong, we'd be getting a net.connman.iwd.Failed */ reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - } else if (nm_streq0(dbus_error, "net.connman.iwd.Aborted")) { + } else if (nm_streq0(dbus_error, "net.connman.iwd.Aborted") && priv->secrets_failed) { /* If agent call was cancelled we'd be getting a net.connman.iwd.Aborted */ reason = NM_DEVICE_STATE_REASON_NO_SECRETS; } @@ -1401,37 +1611,36 @@ network_connect_cb(GObject *source, GAsyncResult *res, gpointer user_data) nm_assert(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG); + disconnect = TRUE; + connection = nm_device_get_applied_connection(device); if (!connection) goto failed; - s_wifi = nm_connection_get_setting_wireless(connection); - if (!s_wifi) - goto failed; - - ssid = nm_setting_wireless_get_ssid(s_wifi); - if (!ssid) + if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, NULL)) goto failed; - ssid_utf8 = _nm_utils_ssid_to_utf8(ssid); - _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to '%s'.", - ssid_utf8); + ssid); nm_device_activate_schedule_stage3_ip_config_start(device); return; failed: - /* Call Disconnect to make sure IWD's autoconnect is disabled */ - cleanup_association_attempt(self, TRUE); + /* If necessary call Disconnect to make sure IWD's autoconnect is disabled */ + cleanup_association_attempt(self, disconnect); - nm_device_queue_state(device, NM_DEVICE_STATE_FAILED, reason); + nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, reason); value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); - if (!priv->can_connect && nm_streq0(get_variant_state(value), "disconnected")) { - priv->can_connect = true; - nm_device_emit_recheck_auto_activate(device); + if (!priv->iwd_autoconnect && nm_streq(get_variant_state(value), "disconnected")) { + schedule_periodic_scan(self, TRUE); + + if (!priv->nm_autoconnect) { + priv->nm_autoconnect = true; + nm_device_emit_recheck_auto_activate(device); + } } g_variant_unref(value); } @@ -1466,14 +1675,12 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data) NMDevice * device = NM_DEVICE(self); gs_unref_variant GVariant *variant = NULL; gs_free_error GError *error = NULL; - NMSettingWireless * s_wireless; - GBytes * ssid; - gs_free char * ssid_utf8 = NULL; + gs_free char * ssid = NULL; variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); if (!variant) { _LOGE(LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) Network.Connect failed: %s", + "Activation: (wifi) {AccessPoint,AdHoc}.Start() failed: %s", error->message); if (nm_utils_error_is_cancelled(error)) @@ -1487,21 +1694,16 @@ act_start_cb(GObject *source, GAsyncResult *res, gpointer user_data) nm_assert(nm_device_get_state(device) == NM_DEVICE_STATE_CONFIG); - s_wireless = nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS); - if (!s_wireless) - goto error; - - ssid = nm_setting_wireless_get_ssid(s_wireless); - if (!ssid) + if (!nm_wifi_connection_get_iwd_ssid_and_security(nm_device_get_applied_connection(device), + &ssid, + NULL)) goto error; - ssid_utf8 = _nm_utils_ssid_to_utf8(ssid); - _LOGI(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Started '%s'.", - ssid_utf8); - + ssid); nm_device_activate_schedule_stage3_ip_config_start(device); + return; error: @@ -1515,14 +1717,13 @@ error: static void act_check_interface(NMDeviceIwd *self) { - NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); - NMDevice * device = NM_DEVICE(self); - NMSettingWireless * s_wireless; - NMSettingWirelessSecurity *s_wireless_sec; - GDBusProxy * proxy = NULL; - GBytes * ssid; - gs_free char * ssid_utf8 = NULL; - const char * mode; + NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice * device = NM_DEVICE(self); + NMSettingWireless * s_wireless; + GDBusProxy * proxy = NULL; + gs_free char * ssid = NULL; + const char * mode; + NMIwdNetworkSecurity security; if (!priv->act_mode_switch) return; @@ -1544,44 +1745,46 @@ act_check_interface(NMDeviceIwd *self) if (!NM_IN_SET(nm_device_get_state(device), NM_DEVICE_STATE_CONFIG)) return; - ssid = nm_setting_wireless_get_ssid(s_wireless); - if (!ssid) + if (!nm_wifi_connection_get_iwd_ssid_and_security(nm_device_get_applied_connection(device), + &ssid, + &security)) goto failed; - ssid_utf8 = _nm_utils_ssid_to_utf8(ssid); - - s_wireless_sec = (NMSettingWirelessSecurity *) nm_device_get_applied_setting( - device, - NM_TYPE_SETTING_WIRELESS_SECURITY); - - if (!s_wireless_sec) { + if (security == NM_IWD_NETWORK_SECURITY_OPEN) { g_dbus_proxy_call(proxy, "StartOpen", - g_variant_new("(s)", ssid_utf8), + g_variant_new("(s)", ssid), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, priv->cancellable, act_start_cb, self); - } else { - const char *psk = nm_setting_wireless_security_get_psk(s_wireless_sec); + } else if (security == NM_IWD_NETWORK_SECURITY_PSK) { + NMSettingWirelessSecurity *s_wireless_sec; + const char * psk; + + s_wireless_sec = (NMSettingWirelessSecurity *) nm_device_get_applied_setting( + device, + NM_TYPE_SETTING_WIRELESS_SECURITY); + psk = nm_setting_wireless_security_get_psk(s_wireless_sec); if (!psk) { - _LOGE(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) No PSK for '%s'.", ssid_utf8); + _LOGE(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) No PSK for '%s'.", ssid); goto failed; } g_dbus_proxy_call(proxy, "Start", - g_variant_new("(ss)", ssid_utf8, psk), + g_variant_new("(ss)", ssid, psk), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, priv->cancellable, act_start_cb, self); - } + } else + goto failed; - _LOGD(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Called Start('%s').", ssid_utf8); + _LOGD(LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) Called Start('%s').", ssid); return; failed: @@ -1718,6 +1921,237 @@ set_powered(NMDeviceIwd *self, gboolean powered) /*****************************************************************************/ +static NMWifiAP * +find_ap_by_supplicant_path(NMDeviceIwd *self, const NMRefString *path) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMWifiAP * tmp; + + c_list_for_each_entry (tmp, &priv->aps_lst_head, aps_lst) + if (nm_wifi_ap_get_supplicant_path(tmp) == path) + return tmp; + + return NULL; +} + +static void +assumed_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, NMDeviceIwd *self) +{ + NMSettingsConnection * sett_conn = nm_active_connection_get_settings_connection(active); + NMActiveConnectionState state = nm_active_connection_get_state(active); + + /* Delete the temporary connection created for an external IWD connection + * (triggered by somebody outside of NM, be it IWD autoconnect or a + * parallel client), unless it's been referenced by a Known Network + * object since, which would remove the EXTERNAL flag. + * + * Note we can't do this too early, e.g. at the same time that we're + * setting the device state to FAILED or DISCONNECTING because the + * connection shouldn't disappear while it's still being used. We do + * this on the connection's transition to DEACTIVATED same as as + * NMManager does for external activations. + */ + if (state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) + return; + + g_signal_handlers_disconnect_by_func(active, assumed_connection_state_changed, NULL); + + if (sett_conn + && NM_FLAGS_HAS(nm_settings_connection_get_flags(sett_conn), + NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + nm_settings_connection_delete(sett_conn, FALSE); +} + +static void +assumed_connection_state_changed_before_managed(NMActiveConnection *active, + GParamSpec * pspec, + NMDeviceIwd * self) +{ + NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMActiveConnectionState state = nm_active_connection_get_state(active); + gboolean disconnect; + + if (state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) + return; + + /* When an assumed connection fails we always get called, even if the + * activation hasn't reached PREPARE or CONFIG, e.g. because of a policy + * or authorization problem in NMManager. .deactivate would only be + * called starting at some stage so we can't rely on that. + * + * If the error happened before PREPARE (where we set a non-NULL + * priv->current_ap) that will mean NM is somehow blocking autoconnect + * so we want to call IWD's Station.Disconnect() to block its + * autoconnect. If this happens during or after PREPARE, we just + * clean up and wait for a new attempt by IWD. + * + * cleanup_association_attempt will clear priv->assumed_ac, disconnect + * this callback from the signal and also send a Disconnect to IWD if + * needed. + * + * Note this function won't be called after IWD transitions to + * "connected" (and NMDevice to IP_CONFIG) as we disconnect from the + * signal at that point, cleanup_association_attempt() will be + * triggered by an IWD state change instead. + */ + disconnect = !priv->current_ap; + cleanup_association_attempt(self, disconnect); +} + +static void +assume_connection(NMDeviceIwd *self, NMWifiAP *ap) +{ + NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingsConnection *sett_conn; + gs_unref_object NMAuthSubject *subject = NULL; + NMActiveConnection * ac; + gs_free_error GError *error = NULL; + + /* We can use the .update_connection / nm_device_emit_recheck_assume + * API but we can also pass an assumed/external activation type + * directly to nm_manager_activate_connection() and skip the + * complicated process of creating a matching connection, taking + * advantage of the Known Networks pointing directly to a mirror + * connection. The only downside seems to be + * nm_manager_activate_connection() goes through the extra + * authorization. + * + * However for now we implement a similar behaviour using a normal + * "managed" activation. For one, assumed/external + * connection state is not reflected in nm_manager_get_state() until + * fully activated. Secondly setting the device state to FAILED + * is treated as ACTIVATED so we'd have to find another way to signal + * that stage2 is failing asynchronously. Thirdly the connection + * becomes "managed" only when ACTIVATED but for IWD it's really + * managed when IP_CONFIG starts. + */ + sett_conn = nm_iwd_manager_get_ap_mirror_connection(nm_iwd_manager_get(), ap); + if (!sett_conn) + goto error; + + subject = nm_auth_subject_new_internal(); + ac = nm_manager_activate_connection( + NM_MANAGER_GET, + sett_conn, + NULL, + nm_dbus_object_get_path(NM_DBUS_OBJECT(ap)), + NM_DEVICE(self), + subject, + NM_ACTIVATION_TYPE_MANAGED, + NM_ACTIVATION_REASON_ASSUME, + NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY, + &error); + + if (!ac) { + _LOGW(LOGD_WIFI, "Activation: (wifi) assume error: %s", error->message); + goto error; + } + + /* If no Known Network existed for this AP, we generated a temporary + * NMSettingsConnection with the EXTERNAL flag. It is not referenced by + * any Known Network objects at this time so we want to delete it if the + * IWD connection ends up failing or a later part of the activation fails + * before IWD created a Known Network. + * Setting the activation type to EXTERNAL would do this by causing + * NM_ACTIVATION_STATE_FLAG_EXTERNAL to be set on the NMActiveConnection + * but we don't want the connection to be marked EXTERNAL because we + * will be assuming the ownership of it in IP_CONFIG or thereabouts. + * + * This callback stays connected forever while the second one gets + * disconnected when we reset the activation type to managed. + */ + g_signal_connect(ac, + "notify::" NM_ACTIVE_CONNECTION_STATE, + G_CALLBACK(assumed_connection_state_changed), + NULL); + g_signal_connect(ac, + "notify::" NM_ACTIVE_CONNECTION_STATE, + G_CALLBACK(assumed_connection_state_changed_before_managed), + self); + priv->assumed_ac = g_object_ref(ac); + + return; + +error: + send_disconnect(self); + + if (sett_conn + && NM_FLAGS_HAS(nm_settings_connection_get_flags(sett_conn), + NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL)) + nm_settings_connection_delete(sett_conn, FALSE); +} + +static void +assumed_connection_progress_to_ip_config(NMDeviceIwd *self, gboolean was_postponed) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDevice * device = NM_DEVICE(self); + NMDeviceState dev_state = nm_device_get_state(device); + + wifi_secrets_cancel(self); + nm_clear_g_source(&priv->assumed_ac_timeout); + + /* NM takes over the activation from this point on so clear the assumed + * activation state and if we were using NM_ACTIVATION_TYPE_ASSUMED or + * _EXTERNAL we'd need to reset the activation type to _MANAGED at this + * point instead of waiting for the ACTIVATED state (as done in + * nm_active_connection_set_state). + */ + cleanup_assumed_connect(self); + + if (dev_state == NM_DEVICE_STATE_NEED_AUTH) + nm_device_state_changed(NM_DEVICE(self), + NM_DEVICE_STATE_CONFIG, + NM_DEVICE_STATE_REASON_NONE); + + /* If stage2 had returned NM_ACT_STAGE_RETURN_POSTPONE, we tell NMDevice + * that stage2 is done. + */ + if (was_postponed) + nm_device_activate_schedule_stage3_ip_config_start(NM_DEVICE(self)); +} + +static void +initial_check_assume(NMDeviceIwd *self) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + const char * network_path_str; + nm_auto_ref_string NMRefString *network_path = NULL; + NMWifiAP * ap = NULL; + gs_unref_variant GVariant *state_value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + gs_unref_variant GVariant *cn_value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "ConnectedNetwork"); + + if (!NM_IN_STRSET(get_variant_state(state_value), "connecting", "connected", "roaming")) + return; + + if (!priv->iwd_autoconnect) { + send_disconnect(self); + return; + } + + if (!cn_value || !g_variant_is_of_type(cn_value, G_VARIANT_TYPE_OBJECT_PATH)) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "ConnectedNetwork property not cached or not an object path"); + return; + } + + network_path_str = g_variant_get_string(cn_value, NULL); + network_path = nm_ref_string_new(network_path_str); + ap = find_ap_by_supplicant_path(self, network_path); + + if (!ap) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "ConnectedNetwork points to an unknown Network %s", + network_path_str); + return; + } + + _LOGD(LOGD_DEVICE | LOGD_WIFI, "assuming connection in initial_check_assume"); + assume_connection(self, ap); +} + static NMActStageReturn act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) { @@ -1740,9 +2174,9 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) s_wireless = nm_connection_get_setting_wireless(connection); g_return_val_if_fail(s_wireless, NM_ACT_STAGE_RETURN_FAILURE); - /* AP mode never uses a specific object or existing scanned AP */ + /* AP, Ad-Hoc modes never use a specific object or existing scanned AP */ mode = nm_setting_wireless_get_mode(s_wireless); - if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_AP)) + if (NM_IN_STRSET(mode, NM_SETTING_WIRELESS_MODE_AP, NM_SETTING_WIRELESS_MODE_ADHOC)) goto add_new; ap_path = nm_active_connection_get_specific_object(NM_ACTIVE_CONNECTION(req)); @@ -1760,14 +2194,16 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_SUCCESS; } - if (nm_streq0(mode, NM_SETTING_WIRELESS_MODE_INFRA)) { - /* Hidden networks not supported at this time */ + /* In infrastructure mode the specific object should be set by now except + * for a first-time connection to a hidden network. If a hidden network is + * a Known Network it should still have been in the AP list. + */ + if (!nm_setting_wireless_get_hidden(s_wireless) || is_connection_known_network(connection)) return NM_ACT_STAGE_RETURN_FAILURE; - } add_new: /* If the user is trying to connect to an AP that NM doesn't yet know about - * (hidden network or something) or starting a Hotspot, create an fake AP + * (hidden network or something) or starting a Hotspot, create a fake AP * from the security settings in the connection. This "fake" AP gets used * until the real one is found in the scan list (Ad-Hoc or Hidden), or until * the device is deactivated (Ad-Hoc or Hotspot). @@ -1808,12 +2244,49 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (NM_IN_STRSET(mode, NULL, NM_SETTING_WIRELESS_MODE_INFRA)) { gs_unref_object GDBusProxy *network_proxy = NULL; NMWifiAP * ap = priv->current_ap; + NMSettingWirelessSecurity * s_wireless_sec; if (!ap) { NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); goto out_fail; } + /* With priv->iwd_autoconnect, if we're assuming a connection because + * of a state change to "connecting", signal stage 2 is still running. + * If "connected" or "roaming", we can go right to the IP_CONFIG state + * and there's nothing left to do in CONFIG. + * If we're assuming the connection because of an agent request we + * switch to NEED_AUTH and actually send the request now that we + * have an activation request. + * + * This all assumes ConnectedNetwork hasn't changed. + */ + if (priv->assumed_ac) { + gboolean result; + + if (!priv->pending_agent_request) { + gs_unref_variant GVariant *value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + + if (nm_streq(get_variant_state(value), "connecting")) { + return NM_ACT_STAGE_RETURN_POSTPONE; + } else { + /* This basically forgets that the connection was "assumed" + * as we can treat it like any connection triggered by a + * Network.Connect() call from now on. + */ + assumed_connection_progress_to_ip_config(self, FALSE); + return NM_ACT_STAGE_RETURN_SUCCESS; + } + } + + result = nm_device_iwd_agent_query(self, priv->pending_agent_request); + g_clear_object(&priv->pending_agent_request); + nm_assert(result); + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + /* 802.1x networks that are not IWD Known Networks will definitely * fail, for other combinations we will let the Connect call fail * or ask us for any missing secrets through the Agent. @@ -1828,15 +2301,28 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) goto out_fail; } - if (!is_connection_known_network(connection) - && nm_setting_wireless_get_hidden(s_wireless)) { - gs_free char *ssid_str = NULL; + priv->secrets_failed = FALSE; + + if (nm_wifi_ap_get_fake(ap)) { + gs_free char *ssid = NULL; + + if (!nm_setting_wireless_get_hidden(s_wireless)) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "Activation: (wifi) target network not known to IWD but is not " + "marked hidden"); + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + goto out_fail; + } + + if (!nm_wifi_connection_get_iwd_ssid_and_security(connection, &ssid, NULL)) { + NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + goto out_fail; + } /* Use Station.ConnectHiddenNetwork method instead of Network proxy. */ - ssid_str = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wireless)); g_dbus_proxy_call(priv->dbus_station_proxy, "ConnectHiddenNetwork", - g_variant_new("(s)", ssid_str), + g_variant_new("(s)", ssid), G_DBUS_CALL_FLAGS_NONE, G_MAXINT, priv->cancellable, @@ -1845,14 +2331,6 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) return NM_ACT_STAGE_RETURN_POSTPONE; } - if (!nm_wifi_ap_get_supplicant_path(ap)) { - _LOGW(LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) network is provisioned but dbus supplicant path for AP " - "unknown"); - NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); - goto out_fail; - } - network_proxy = nm_iwd_manager_get_dbus_interface( nm_iwd_manager_get(), nm_ref_string_get_str(nm_wifi_ap_get_supplicant_path(ap)), @@ -1868,6 +2346,15 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) if (!priv->cancellable) priv->cancellable = g_cancellable_new(); + s_wireless_sec = nm_connection_get_setting_wireless_security(connection); + if (s_wireless_sec + && nm_streq0(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), "owe")) { + _LOGI(LOGD_WIFI, + "An OWE connection is requested but IWD may connect to either an OWE " + "or unsecured network and there won't be any indication of whether " + "encryption is in use -- proceed at your own risk!"); + } + /* Call Network.Connect. No timeout because IWD already handles * timeouts. */ @@ -1951,31 +2438,26 @@ static void schedule_periodic_scan(NMDeviceIwd *self, gboolean initial_scan) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); - GVariant * value; - gboolean disconnected = TRUE; guint interval; - if (priv->can_scan) { - value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); - disconnected = nm_streq0(get_variant_state(value), "disconnected"); - g_variant_unref(value); - } - - /* Start scan immediately after a disconnect, mode change or - * device UP, otherwise wait 10 seconds. When connected, update - * AP list mainly on UI requests. + /* Automatically start a scan after a disconnect, mode change or device UP, + * otherwise scan periodically every 10 seconds if needed for NM's + * autoconnect. There's no need to scan When using IWD's autoconnect or + * when connected, we update the AP list on UI requests. * - * (initial_scan && disconnected) override priv->scanning below - * because of an IWD quirk where a device will often be in the - * autoconnect state and scanning at the time of our initial_scan, - * but our logic will then send it a Disconnect() causing IWD to - * exit autoconnect and interrupt the ongoing scan, meaning that - * we still want a new scan ASAP. + * (initial_scan && disconnected && !priv->iwd_autoconnect) override + * priv->scanning below because of an IWD quirk where a device will often + * be in the autoconnect state and scanning at the time of our initial_scan, + * but our logic will then send it a Disconnect() causing IWD to exit + * autoconnect and interrupt the ongoing scan, meaning that we still want + * a new scan ASAP. */ - if (!priv->can_scan || !disconnected || priv->scan_requested || priv->scanning) + if (!priv->can_scan || priv->scan_requested || priv->current_ap || priv->iwd_autoconnect) interval = -1; - else if (initial_scan) + else if (initial_scan && priv->scanning) interval = 0; + else if (priv->scanning) + interval = -1; else if (!priv->periodic_scan_id) interval = 10; else @@ -1997,7 +2479,8 @@ set_can_scan(NMDeviceIwd *self, gboolean can_scan) priv->can_scan = can_scan; - schedule_periodic_scan(self, TRUE); + if (!priv->iwd_autoconnect) + schedule_periodic_scan(self, TRUE); } static void @@ -2008,6 +2491,8 @@ device_state_changed(NMDevice * device, { NMDeviceIwd * self = NM_DEVICE_IWD(device); NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMSettingWireless * s_wireless; + const char * mode; switch (new_state) { case NM_DEVICE_STATE_UNMANAGED: @@ -2024,15 +2509,22 @@ device_state_changed(NMDevice * device, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); } break; - case NM_DEVICE_STATE_NEED_AUTH: - break; - case NM_DEVICE_STATE_IP_CHECK: - break; - case NM_DEVICE_STATE_ACTIVATED: - break; - case NM_DEVICE_STATE_FAILED: - break; case NM_DEVICE_STATE_DISCONNECTED: + if (old_state == NM_DEVICE_STATE_UNAVAILABLE) + initial_check_assume(self); + break; + case NM_DEVICE_STATE_IP_CONFIG: + s_wireless = + (NMSettingWireless *) nm_device_get_applied_setting(device, NM_TYPE_SETTING_WIRELESS); + mode = nm_setting_wireless_get_mode(s_wireless); + if (!priv->periodic_update_id + && NM_IN_STRSET(mode, + NULL, + NM_SETTING_WIRELESS_MODE_INFRA, + NM_SETTING_WIRELESS_MODE_ADHOC)) { + priv->periodic_update_id = g_timeout_add_seconds(6, periodic_update_cb, self); + periodic_update(self); + } break; default: break; @@ -2128,7 +2620,7 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case PROP_BITRATE: - g_value_set_uint(value, 65000); + g_value_set_uint(value, priv->rate); break; case PROP_CAPABILITIES: g_value_set_uint(value, priv->capabilities); @@ -2164,51 +2656,149 @@ state_changed(NMDeviceIwd *self, const char *new_state) NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); NMDevice * device = NM_DEVICE(self); NMDeviceState dev_state = nm_device_get_state(device); + gboolean nm_connection = priv->current_ap || priv->assumed_ac; gboolean iwd_connection = FALSE; - gboolean can_connect = priv->can_connect; + NMWifiAP * ap = NULL; + gboolean can_connect = priv->nm_autoconnect; _LOGI(LOGD_DEVICE | LOGD_WIFI, "new IWD device state is %s", new_state); - if (dev_state >= NM_DEVICE_STATE_CONFIG && dev_state <= NM_DEVICE_STATE_ACTIVATED) - iwd_connection = TRUE; + if (NM_IN_STRSET(new_state, "connecting", "connected", "roaming")) { + gs_unref_variant GVariant *value = NULL; + const char * network_path_str; + nm_auto_ref_string NMRefString *network_path = NULL; + + value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "ConnectedNetwork"); + if (!value || !g_variant_is_of_type(value, G_VARIANT_TYPE_OBJECT_PATH)) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "ConnectedNetwork property not cached or not an object path"); + return; + } + + iwd_connection = TRUE; + network_path_str = g_variant_get_string(value, NULL); + network_path = nm_ref_string_new(network_path_str); + ap = find_ap_by_supplicant_path(self, network_path); + + if (!ap) { + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "ConnectedNetwork points to an unknown Network %s", + network_path_str); + return; + } + } /* Don't allow scanning while connecting, disconnecting or roaming */ set_can_scan(self, NM_IN_STRSET(new_state, "connected", "disconnected")); - priv->can_connect = FALSE; + priv->nm_autoconnect = FALSE; - if (NM_IN_STRSET(new_state, "connecting", "connected", "roaming")) { + if (nm_connection && iwd_connection && priv->current_ap && ap != priv->current_ap) { + gboolean switch_ap = priv->iwd_autoconnect && priv->assumed_ac; + + _LOGW(LOGD_DEVICE | LOGD_WIFI, + "IWD is connecting to the wrong AP, %s activation", + switch_ap ? "replacing" : "aborting"); + cleanup_association_attempt(self, !switch_ap); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + + if (switch_ap) + assume_connection(self, ap); + return; + } + + if (priv->iwd_autoconnect && iwd_connection) { + if (dev_state < NM_DEVICE_STATE_DISCONNECTED) + return; + + /* If IWD is in any state other than disconnected and the NMDevice is + * in DISCONNECTED then someone else, possibly IWD's autoconnect, has + * commanded an action and we need to update our NMDevice's state to + * match, including finding the NMSettingsConnection and NMWifiAP + * matching the network pointed to by Station.ConnectedNetwork. + * + * If IWD is in the connected state and we're in CONFIG, we only have + * to signal that the existing connection request has advanced to a new + * state. If the connection request came from NM, we must have used + * Network.Connect() so that method call's callback will update the + * connection request, otherwise we do it here. + * + * If IWD is disconnecting or just disconnected, the common code below + * (independent from priv->iwd_autoconnect) will handle this case. + * If IWD is disconnecting but we never saw a connection request in the + * first place (maybe because we're only startig up) we won't be + * setting up an NMActiveConnection just to put the NMDevice in the + * DEACTIVATING state and we ignore this case. + * + * If IWD was in the disconnected state and transitioned to + * "connecting" but we were already in NEED_AUTH because we handled an + * agent query -- IWD normally stays in "disconnected" until it has all + * the secrets -- we record this fact and remain in NEED_AUTH. + */ + if (!nm_connection) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "This is a new connection, 'assuming' it"); + assume_connection(self, ap); + return; + } + + if (priv->assumed_ac && dev_state >= NM_DEVICE_STATE_PREPARE + && dev_state < NM_DEVICE_STATE_IP_CONFIG + && NM_IN_STRSET(new_state, "connected", "roaming")) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "Updating assumed activation state"); + assumed_connection_progress_to_ip_config(self, TRUE); + return; + } + + if (priv->assumed_ac) { + _LOGD(LOGD_DEVICE | LOGD_WIFI, "Clearing assumed activation timeout"); + nm_clear_g_source(&priv->assumed_ac_timeout); + return; + } + } else if (!priv->iwd_autoconnect && iwd_connection) { /* If we were connecting, do nothing, the confirmation of * a connection success is handled in the Device.Connect * method return callback. Otherwise, IWD must have connected * without Network Manager's will so for simplicity force a * disconnect. */ - if (iwd_connection) + if (nm_connection) return; - _LOGW(LOGD_DEVICE | LOGD_WIFI, "Unsolicited connection success, asking IWD to disconnect"); + _LOGW(LOGD_DEVICE | LOGD_WIFI, "Unsolicited connection, asking IWD to disconnect"); send_disconnect(self); } else if (NM_IN_STRSET(new_state, "disconnecting", "disconnected")) { - /* Call Disconnect on the IWD device object to make sure it - * disables its own autoconnect. + /* If necessary, call Disconnect on the IWD device object to make sure + * it disables its autoconnect. */ - send_disconnect(self); + if ((!priv->iwd_autoconnect + || nm_device_autoconnect_blocked_get(device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL)) + && !priv->wifi_secrets_id && !priv->pending_agent_request) + send_disconnect(self); /* * If IWD is still handling the Connect call, let our Connect * callback for the dbus method handle the failure. The main - * reason we can't handle the failure here is because the method - * callback will have more information on the specific failure - * reason. + * reason we don't want to handle the failure here is because the + * method callback will have more information on the specific + * failure reason. + * + * If IWD is handling an autoconnect agent call, let the agent's + * Cancel() handler take care of this. */ - if (NM_IN_SET(dev_state, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH)) + if (NM_IN_SET(dev_state, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_NEED_AUTH) + && !priv->assumed_ac) + return; + if (NM_IN_SET(dev_state, NM_DEVICE_STATE_NEED_AUTH) && priv->assumed_ac) return; - if (iwd_connection) + if (nm_connection) { + cleanup_association_attempt(self, FALSE); nm_device_state_changed(device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + } } else if (!nm_streq(new_state, "unknown")) { _LOGE(LOGD_WIFI, "State %s unknown", new_state); return; @@ -2217,8 +2807,8 @@ state_changed(NMDeviceIwd *self, const char *new_state) /* Don't allow new connection until iwd exits disconnecting and no * Connect callback is pending. */ - if (NM_IN_STRSET(new_state, "disconnected")) { - priv->can_connect = TRUE; + if (!priv->iwd_autoconnect && NM_IN_STRSET(new_state, "disconnected")) { + priv->nm_autoconnect = TRUE; if (!can_connect) nm_device_emit_recheck_auto_activate(device); } @@ -2239,7 +2829,7 @@ scanning_changed(NMDeviceIwd *self, gboolean new_scanning) if (!priv->scanning) { update_aps(self); - if (!priv->scan_requested) + if (!priv->scan_requested && !priv->iwd_autoconnect) schedule_periodic_scan(self, FALSE); } } @@ -2281,7 +2871,6 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); GDBusInterface * interface; - GVariant * value; nm_device_queue_recheck_available(NM_DEVICE(self), NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, @@ -2340,24 +2929,11 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) if (new_powered && !priv->dbus_ap_proxy && !priv->dbus_adhoc_proxy) { interface = g_dbus_object_get_interface(priv->dbus_obj, NM_IWD_STATION_INTERFACE); if (!interface) { - /* No Station interface on the device object. Check if the - * "State" property is present on the Device interface, that - * would mean we're dealing with an IWD version from before the - * Device/Station split (0.7 or earlier) and we can easily - * handle that by making priv->dbus_device_proxy and - * priv->dbus_station_proxy both point at the Device interface. - */ - value = g_dbus_proxy_get_cached_property(priv->dbus_device_proxy, "State"); - if (value) { - g_variant_unref(value); - interface = g_object_ref(G_DBUS_INTERFACE(priv->dbus_device_proxy)); - } else { - _LOGE(LOGD_WIFI, - "Interface %s not found on obj %s", - NM_IWD_STATION_INTERFACE, - g_dbus_object_get_object_path(priv->dbus_obj)); - interface = NULL; - } + _LOGE(LOGD_WIFI, + "Interface %s not found on obj %s", + NM_IWD_STATION_INTERFACE, + g_dbus_object_get_object_path(priv->dbus_obj)); + interface = NULL; } } else interface = NULL; @@ -2370,6 +2946,8 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) } if (interface) { + GVariant *value; + priv->dbus_station_proxy = G_DBUS_PROXY(interface); g_signal_connect(priv->dbus_station_proxy, "g-properties-changed", @@ -2385,11 +2963,21 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) g_variant_unref(value); update_aps(self); + + /* When a device is brought UP in station mode, including after a mode + * switch, IWD re-enables autoconnect. This is unlike NM's autoconnect + * where a mode change doesn't interfere with the + * BLOCKED_MANUAL_DISCONNECT flag. + */ + if (priv->iwd_autoconnect) { + nm_device_autoconnect_blocked_unset(NM_DEVICE(self), + NM_DEVICE_AUTOCONNECT_BLOCKED_INTERNAL); + } } else { set_can_scan(self, FALSE); priv->scanning = FALSE; priv->scan_requested = FALSE; - priv->can_connect = FALSE; + priv->nm_autoconnect = FALSE; cleanup_association_attempt(self, FALSE); remove_all_aps(self); } @@ -2408,6 +2996,36 @@ device_properties_changed(GDBusProxy *proxy, powered_changed(self, new_bool); } +static void +config_changed(NMConfig * config, + NMConfigData * config_data, + NMConfigChangeFlags changes, + NMConfigData * old_data, + NMDeviceIwd * self) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + gboolean old_iwd_ac = priv->iwd_autoconnect; + + priv->iwd_autoconnect = + nm_config_data_get_device_config_boolean(config_data, + NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_IWD_AUTOCONNECT, + NM_DEVICE(self), + TRUE, + TRUE); + + if (old_iwd_ac != priv->iwd_autoconnect && priv->dbus_station_proxy && !priv->current_ap) { + gs_unref_variant GVariant *value = NULL; + + if (!priv->iwd_autoconnect + && !nm_device_autoconnect_blocked_get(NM_DEVICE(self), + NM_DEVICE_AUTOCONNECT_BLOCKED_ALL)) + send_disconnect(self); + + value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + state_changed(self, get_variant_state(value)); + } +} + void nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) { @@ -2432,6 +3050,8 @@ nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) powered_changed(self, FALSE); priv->act_mode_switch = FALSE; + + g_signal_handlers_disconnect_by_func(nm_config_get(), config_changed, self); } if (!object) @@ -2494,6 +3114,13 @@ nm_device_iwd_set_dbus_object(NMDeviceIwd *self, GDBusObject *object) _notify(self, PROP_CAPABILITIES); } + /* Update iwd_autoconnect before any state_changed call */ + g_signal_connect(nm_config_get(), + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK(config_changed), + self); + config_changed(NULL, NM_CONFIG_GET_DATA, 0, NULL, self); + g_variant_unref(value); value = g_dbus_proxy_get_cached_property(priv->dbus_device_proxy, "Powered"); powered = get_variant_boolean(value, "Powered"); @@ -2513,24 +3140,127 @@ error: gboolean nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) { - NMActRequest * req; + NMDevice * device = NM_DEVICE(self); + NMDeviceIwdPrivate * priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMDeviceState state = nm_device_get_state(device); const char * setting_name; const char * setting_key; gboolean replied; + NMWifiAP * ap; NMSecretAgentGetSecretsFlags get_secret_flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; + nm_auto_ref_string NMRefString *network_path = NULL; - req = nm_device_get_act_request(NM_DEVICE(self)); - if (!req) + if (!invocation) { + gs_unref_variant GVariant *value = + g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + gboolean disconnect; + + if (!priv->wifi_secrets_id && !priv->pending_agent_request) + return FALSE; + + _LOGI(LOGD_WIFI, "IWD agent request is being cancelled"); + wifi_secrets_cancel(self); + + if (state == NM_DEVICE_STATE_NEED_AUTH) + nm_device_state_changed(device, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); + + /* The secrets request is being cancelled. If we don't have an assumed + * connection than we've probably called Network.Connect and that method + * call's callback is going to handle the failure. And if the state was + * not "disconnected" then let the state change handler process the + * failure. + */ + if (!priv->assumed_ac) + return TRUE; + + if (!nm_streq(get_variant_state(value), "disconnected")) + return TRUE; + + disconnect = nm_device_autoconnect_blocked_get(device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL); + cleanup_association_attempt(self, disconnect); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return TRUE; + } + + if (state > NM_DEVICE_STATE_CONFIG && state < NM_DEVICE_STATE_DEACTIVATING) { + _LOGW(LOGD_WIFI, "Can't handle the IWD agent request in current device state"); return FALSE; + } + + if (priv->wifi_secrets_id || priv->pending_agent_request) { + _LOGW(LOGD_WIFI, "There's already a pending agent request for this device"); + return FALSE; + } + + network_path = nm_ref_string_new(get_agent_request_network_path(invocation)); + ap = find_ap_by_supplicant_path(self, network_path); + if (!ap) { + _LOGW(LOGD_WIFI, "IWD Network object not found for the agent request"); + return FALSE; + } + + if (priv->assumed_ac) { + const char *ac_ap_path = nm_active_connection_get_specific_object(priv->assumed_ac); + + if (!nm_streq(ac_ap_path, nm_dbus_object_get_path(NM_DBUS_OBJECT(ap)))) { + _LOGW(LOGD_WIFI, + "Dropping an existing assumed connection to create a new one based on the IWD " + "agent request network parameter"); + + if (priv->current_ap) + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + cleanup_association_attempt(self, FALSE); + priv->pending_agent_request = g_object_ref(invocation); + assume_connection(self, ap); + return TRUE; + } + + if (state != NM_DEVICE_STATE_CONFIG) { + _LOGI(LOGD_WIFI, "IWD agent request deferred until in CONFIG"); + priv->pending_agent_request = g_object_ref(invocation); + return TRUE; + } + + /* Otherwise handle as usual */ + } else if (!priv->current_ap) { + _LOGI(LOGD_WIFI, "IWD is asking for secrets without explicit connect request"); + + if (priv->iwd_autoconnect) { + priv->pending_agent_request = g_object_ref(invocation); + assume_connection(self, ap); + return TRUE; + } + + send_disconnect(self); + return FALSE; + } else if (priv->current_ap) { + if (priv->current_ap != ap) { + _LOGW(LOGD_WIFI, "IWD agent request for a wrong network object"); + cleanup_association_attempt(self, TRUE); + nm_device_state_changed(device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return FALSE; + } + + /* Otherwise handle as usual */ + } if (!try_reply_agent_request(self, - nm_act_request_get_applied_connection(req), + nm_device_get_applied_connection(device), invocation, &setting_name, &setting_key, - &replied)) + &replied)) { + priv->secrets_failed = TRUE; return FALSE; + } if (replied) return TRUE; @@ -2543,17 +3273,83 @@ nm_device_iwd_agent_query(NMDeviceIwd *self, GDBusMethodInvocation *invocation) * Connection timestamp is set after activation or after first * activation failure (to 0). */ - if (nm_settings_connection_get_timestamp(nm_act_request_get_settings_connection(req), NULL)) + if (nm_settings_connection_get_timestamp(nm_device_get_settings_connection(device), NULL)) get_secret_flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; - nm_device_state_changed(NM_DEVICE(self), - NM_DEVICE_STATE_NEED_AUTH, - NM_DEVICE_STATE_REASON_NO_SECRETS); + nm_device_state_changed(device, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NO_SECRETS); wifi_secrets_get_one(self, setting_name, get_secret_flags, setting_key, invocation); return TRUE; } +void +nm_device_iwd_network_add_remove(NMDeviceIwd *self, GDBusProxy *network, bool add) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + NMWifiAP * ap = NULL; + bool recheck; + nm_auto_ref_string NMRefString *bss_path = NULL; + + bss_path = nm_ref_string_new(g_dbus_proxy_get_object_path(network)); + ap = find_ap_by_supplicant_path(self, bss_path); + + /* We could schedule an update_aps(self) idle call here but up to IWD 1.9 + * when a hidden network connection is attempted, that network is initially + * only added as a Network object but not shown in GetOrderedNetworks() + * return values, and for some corner case scenarios it's beneficial to + * have that Network reflected in our ap list so that we don't attempt + * calling ConnectHiddenNetwork() on it, as that will fail in 1.9. But we + * can skip recheck-available if we're currently scanning or in the middle + * of a GetOrderedNetworks() call as that will trigger the recheck too. + */ + recheck = priv->enabled && !priv->scanning && !priv->networks_requested; + + if (!add) { + if (ap) { + ap_add_remove(self, FALSE, ap, recheck); + priv->networks_changed |= !recheck; + } + + return; + } + + if (!ap) { + ap = ap_from_network(self, + network, + bss_path, + nm_utils_get_monotonic_timestamp_msec(), + -10000); + if (!ap) + return; + + ap_add_remove(self, TRUE, ap, recheck); + g_object_unref(ap); + priv->networks_changed |= !recheck; + return; + } +} + +static void +autoconnect_changed(NMDevice *device, GParamSpec *pspec, NMDeviceIwd *self) +{ + NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); + gs_unref_variant GVariant *value = NULL; + + /* Note IWD normally remains in "disconnected" during a secret request + * and we don't want to interrupt it by calling Station.Disconnect(). + */ + if (!priv->dbus_station_proxy || !priv->iwd_autoconnect + || !nm_device_autoconnect_blocked_get(device, NM_DEVICE_AUTOCONNECT_BLOCKED_ALL) + || priv->wifi_secrets_id || priv->pending_agent_request) + return; + + value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + if (!nm_streq(get_variant_state(value), "disconnected")) + return; + + send_disconnect(self); +} + /*****************************************************************************/ static const char * @@ -2573,6 +3369,8 @@ nm_device_iwd_init(NMDeviceIwd *self) c_list_init(&priv->aps_lst_head); + g_signal_connect(self, "notify::" NM_DEVICE_AUTOCONNECT, G_CALLBACK(autoconnect_changed), self); + /* Make sure the manager is running */ (void) nm_iwd_manager_get(); } @@ -2602,6 +3400,7 @@ dispose(GObject *object) nm_clear_g_cancellable(&priv->cancellable); + g_signal_handlers_disconnect_by_func(self, autoconnect_changed, self); nm_device_iwd_set_dbus_object(self, NULL); G_OBJECT_CLASS(nm_device_iwd_parent_class)->dispose(object); @@ -2643,6 +3442,13 @@ nm_device_iwd_class_init(NMDeviceIwdClass *klass) device_class->deactivate_async = deactivate_async; device_class->can_reapply_change = can_reapply_change; + /* Stage 1 needed only for the set_current_ap() call. Stage 2 is + * needed if we're assuming a connection still in the "connecting" + * state or on an agent request. + */ + device_class->act_stage1_prepare_also_for_external_or_assume = TRUE; + device_class->act_stage2_config_also_for_external_or_assume = TRUE; + device_class->state_changed = device_state_changed; obj_properties[PROP_MODE] = g_param_spec_uint(NM_DEVICE_IWD_MODE, diff --git a/src/devices/wifi/nm-device-iwd.h b/src/core/devices/wifi/nm-device-iwd.h index e364beaf..ce94c9ea 100644 --- a/src/devices/wifi/nm-device-iwd.h +++ b/src/core/devices/wifi/nm-device-iwd.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Intel Corporation */ @@ -44,4 +44,6 @@ void _nm_device_iwd_request_scan(NMDeviceIwd * self, GVariant * options, GDBusMethodInvocation *invocation); +void nm_device_iwd_network_add_remove(NMDeviceIwd *device, GDBusProxy *network, bool add); + #endif /* __NETWORKMANAGER_DEVICE_IWD_H__ */ diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/core/devices/wifi/nm-device-olpc-mesh.c index 22e94a6d..af83c4a3 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/core/devices/wifi/nm-device-olpc-mesh.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Dan Williams <dcbw@redhat.com> * Sjoerd Simons <sjoerd.simons@collabora.co.uk> @@ -8,7 +8,7 @@ * Copyright (C) 2009 One Laptop per Child */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-olpc-mesh.h" @@ -30,8 +30,8 @@ #include "nm-manager.h" #include "platform/nm-platform.h" +#define _NMLOG_DEVICE_TYPE NMDeviceOlpcMesh #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceOlpcMesh); /*****************************************************************************/ @@ -460,16 +460,16 @@ constructed(GObject *object) NMDevice * nm_device_olpc_mesh_new(const char *iface) { - return (NMDevice *) g_object_new(NM_TYPE_DEVICE_OLPC_MESH, - NM_DEVICE_IFACE, - iface, - NM_DEVICE_TYPE_DESC, - "802.11 OLPC Mesh", - NM_DEVICE_DEVICE_TYPE, - NM_DEVICE_TYPE_OLPC_MESH, - NM_DEVICE_LINK_TYPE, - NM_LINK_TYPE_OLPC_MESH, - NULL); + return g_object_new(NM_TYPE_DEVICE_OLPC_MESH, + NM_DEVICE_IFACE, + iface, + NM_DEVICE_TYPE_DESC, + "802.11 OLPC Mesh", + NM_DEVICE_DEVICE_TYPE, + NM_DEVICE_TYPE_OLPC_MESH, + NM_DEVICE_LINK_TYPE, + NM_LINK_TYPE_OLPC_MESH, + NULL); } static void diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/core/devices/wifi/nm-device-olpc-mesh.h index d31c86fb..79b7fd5d 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.h +++ b/src/core/devices/wifi/nm-device-olpc-mesh.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Dan Williams <dcbw@redhat.com> * Sjoerd Simons <sjoerd.simons@collabora.co.uk> diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index 2e5317fd..fb987600 100644 --- a/src/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-wifi-p2p.h" @@ -27,8 +27,8 @@ #include "platform/nmp-object.h" #include "settings/nm-settings.h" +#define _NMLOG_DEVICE_TYPE NMDeviceWifiP2P #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceWifiP2P); /*****************************************************************************/ diff --git a/src/devices/wifi/nm-device-wifi-p2p.h b/src/core/devices/wifi/nm-device-wifi-p2p.h index 03e49311..d1aadd8e 100644 --- a/src/devices/wifi/nm-device-wifi-p2p.h +++ b/src/core/devices/wifi/nm-device-wifi-p2p.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-device-wifi.c b/src/core/devices/wifi/nm-device-wifi.c index 980916dd..042d4887 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/core/devices/wifi/nm-device-wifi.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-wifi.h" #include <netinet/in.h> #include <unistd.h> +#include <linux/if_ether.h> #include "nm-glib-aux/nm-ref-string.h" #include "nm-glib-aux/nm-c-list.h" @@ -41,8 +42,8 @@ #include "nm-core-internal.h" #include "nm-config.h" +#define _NMLOG_DEVICE_TYPE NMDeviceWifi #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceWifi); #define SCAN_INTERVAL_SEC_MIN 3 #define SCAN_INTERVAL_SEC_STEP 20 @@ -728,6 +729,7 @@ periodic_update(NMDeviceWifi *self) NMDeviceWifiPrivate *priv; int ifindex; guint32 new_rate; + int percent; if (nm_device_get_state(NM_DEVICE(self)) != NM_DEVICE_STATE_ACTIVATED) { /* BSSID and signal strength have meaningful values only if the device @@ -757,23 +759,22 @@ periodic_update(NMDeviceWifi *self) if (ifindex <= 0) g_return_if_reached(); - if (priv->current_ap) { - int percent; - - percent = nm_platform_wifi_get_quality(nm_device_get_platform(NM_DEVICE(self)), ifindex); - if (percent >= 0 && percent <= 100) { - if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { + if (priv->current_ap + && nm_platform_wifi_get_station(nm_device_get_platform(NM_DEVICE(self)), + ifindex, + NULL, + &percent, + &new_rate)) { + if (nm_wifi_ap_set_strength(priv->current_ap, (gint8) percent)) { #if NM_MORE_LOGGING - _ap_dump(self, LOGL_TRACE, priv->current_ap, "updated", 0); + _ap_dump(self, LOGL_TRACE, priv->current_ap, "updated", 0); #endif - } } - } - new_rate = nm_platform_wifi_get_rate(nm_device_get_platform(NM_DEVICE(self)), ifindex); - if (new_rate != priv->rate) { - priv->rate = new_rate; - _notify(self, PROP_BITRATE); + if (new_rate != priv->rate) { + priv->rate = new_rate; + _notify(self, PROP_BITRATE); + } } } @@ -1744,6 +1745,23 @@ _scan_kickoff(NMDeviceWifi *self) return; } + if (priv->scan_last_complete_msec + 200 > now_msec) { + gint32 timeout_msec = priv->scan_last_complete_msec + 200 - now_msec; + + /* after a scan just completed, it is ratelimited for another 200 msec. This is in + * addition to our rate limiting above (where scanning can take longer than our rate limit + * duration). + * + * This gives the device a chance to autoconnect. Also, if a scanning just completed, + * we want to back off a bit before starting again. */ + _LOGT_scan("kickoff: don't scan (rate limited for another %d.%03d sec after previous scan)", + timeout_msec / 1000, + timeout_msec % 1000); + nm_clear_g_source(&priv->scan_kickoff_timeout_id); + priv->scan_kickoff_timeout_id = g_timeout_add(timeout_msec, _scan_kickoff_timeout_cb, self); + return; + } + if (priv->scan_explicit_requested) { if (!priv->scan_explicit_allowed) { _LOGT_scan("kickoff: don't scan (explicit scan requested but not allowed)"); @@ -3136,6 +3154,9 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) NMSettingWireless * s_wireless; GError * error = NULL; guint timeout; + NMActRequest * request; + NMActiveConnection * master_ac; + NMDevice * master; nm_clear_g_source(&priv->sup_timeout_id); nm_clear_g_source(&priv->link_timeout_id); @@ -3209,6 +3230,15 @@ act_stage2_config(NMDevice *device, NMDeviceStateReason *out_failure_reason) goto out_fail; } + /* Tell the supplicant in which bridge the interface is */ + if ((request = nm_device_get_act_request(device)) + && (master_ac = nm_active_connection_get_master(NM_ACTIVE_CONNECTION(request))) + && (master = nm_active_connection_get_device(master_ac)) + && nm_device_get_device_type(master) == NM_DEVICE_TYPE_BRIDGE) { + nm_supplicant_interface_set_bridge(priv->sup_iface, nm_device_get_iface(master)); + } else + nm_supplicant_interface_set_bridge(priv->sup_iface, NULL); + nm_supplicant_interface_assoc(priv->sup_iface, config, supplicant_iface_assoc_cb, self); /* Set up a timeout on the association attempt */ @@ -3357,31 +3387,33 @@ activation_success_handler(NMDevice *device) g_warn_if_fail(priv->current_ap); if (priv->current_ap) { if (nm_wifi_ap_get_fake(priv->current_ap)) { - gboolean ap_changed = FALSE; + gboolean ap_changed = FALSE; + gboolean update_bssid = !nm_wifi_ap_get_address(priv->current_ap); + gboolean update_rate = !nm_wifi_ap_get_max_bitrate(priv->current_ap); + NMEtherAddr bssid; + guint32 rate; /* If the activation AP hasn't been seen by the supplicant in a scan * yet, it will be "fake". This usually happens for Ad-Hoc and * AP-mode connections. Fill in the details from the device itself * until the supplicant sends the scan result. */ - if (!nm_wifi_ap_get_address(priv->current_ap)) { - guint8 bssid[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - gs_free char *bssid_str = NULL; - - if (nm_platform_wifi_get_bssid(nm_device_get_platform(device), ifindex, bssid) - && nm_ethernet_address_is_valid(bssid, ETH_ALEN)) { - bssid_str = nm_utils_hwaddr_ntoa(bssid, ETH_ALEN); - ap_changed |= nm_wifi_ap_set_address(priv->current_ap, bssid_str); - } - } if (!nm_wifi_ap_get_freq(priv->current_ap)) ap_changed |= nm_wifi_ap_set_freq( priv->current_ap, nm_platform_wifi_get_frequency(nm_device_get_platform(device), ifindex)); - if (!nm_wifi_ap_get_max_bitrate(priv->current_ap)) - ap_changed |= nm_wifi_ap_set_max_bitrate( - priv->current_ap, - nm_platform_wifi_get_rate(nm_device_get_platform(device), ifindex)); + + if ((update_bssid || update_rate) + && nm_platform_wifi_get_station(nm_device_get_platform(device), + ifindex, + update_bssid ? &bssid : NULL, + NULL, + update_rate ? &rate : NULL)) { + if (update_bssid && nm_ether_addr_is_valid(&bssid)) + ap_changed |= nm_wifi_ap_set_address_bin(priv->current_ap, &bssid); + if (update_rate) + ap_changed |= nm_wifi_ap_set_max_bitrate(priv->current_ap, rate); + } if (ap_changed) _ap_dump(self, LOGL_DEBUG, priv->current_ap, "updated", 0); diff --git a/src/devices/wifi/nm-device-wifi.h b/src/core/devices/wifi/nm-device-wifi.h index 713c1480..d9e9038c 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/core/devices/wifi/nm-device-wifi.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2016 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index c7e99e0b..b4b019d3 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -1,21 +1,21 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Intel Corporation */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-iwd-manager.h" #include <net/if.h> -#include "nm-logging.h" #include "nm-core-internal.h" #include "nm-manager.h" #include "nm-device-iwd.h" #include "nm-wifi-utils.h" #include "nm-glib-aux/nm-random-utils.h" #include "settings/nm-settings.h" +#include "nm-std-aux/nm-dbus-compat.h" /*****************************************************************************/ @@ -39,6 +39,7 @@ typedef struct { guint agent_id; char * agent_path; GHashTable * known_networks; + NMDeviceIwd * last_agent_call_device; } NMIwdManagerPrivate; struct _NMIwdManager { @@ -87,7 +88,8 @@ G_DEFINE_TYPE(NMIwdManager, nm_iwd_manager, G_TYPE_OBJECT) /*****************************************************************************/ -static void mirror_8021x_connection_take_and_delete(NMSettingsConnection *sett_conn); +static void mirror_connection_take_and_delete(NMSettingsConnection *sett_conn, + KnownNetworkData * data); /*****************************************************************************/ @@ -117,6 +119,59 @@ get_property_string_or_null(GDBusProxy *proxy, const char *property) return get_variant_string_or_null(value); } +static gboolean +get_property_bool(GDBusProxy *proxy, const char *property, gboolean default_val) +{ + gs_unref_variant GVariant *value = NULL; + + if (!proxy || !property) + return default_val; + + value = g_dbus_proxy_get_cached_property(proxy, property); + if (!value || !g_variant_is_of_type(value, G_VARIANT_TYPE_BOOLEAN)) + return default_val; + + return g_variant_get_boolean(value); +} + +static NMDeviceIwd * +get_device_from_network(NMIwdManager *self, GDBusProxy *network) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char * ifname; + const char * device_path; + NMDevice * device; + gs_unref_object GDBusInterface *device_obj = NULL; + + /* Try not to rely on the path of the Device being a prefix of the + * Network's object path. + */ + + device_path = get_property_string_or_null(network, "Device"); + if (!device_path) { + _LOGD("Device not cached for network at %s", g_dbus_proxy_get_object_path(network)); + return NULL; + } + + device_obj = g_dbus_object_manager_get_interface(priv->object_manager, + device_path, + NM_IWD_DEVICE_INTERFACE); + + ifname = get_property_string_or_null(G_DBUS_PROXY(device_obj), "Name"); + if (!ifname) { + _LOGD("Name not cached for device at %s", device_path); + return NULL; + } + + device = nm_manager_get_device(priv->manager, ifname, NM_DEVICE_TYPE_WIFI); + if (!device || !NM_IS_DEVICE_IWD(device)) { + _LOGD("NM device %s is not an IWD-managed device", ifname); + return NULL; + } + + return NM_DEVICE_IWD(device); +} + static void agent_dbus_method_cb(GDBusConnection * connection, const char * sender, @@ -129,12 +184,10 @@ agent_dbus_method_cb(GDBusConnection * connection, { NMIwdManager * self = user_data; NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - const char * network_path, *device_path, *ifname; - gs_unref_object GDBusInterface *network = NULL, *device_obj = NULL; - int ifindex; - NMDevice * device; - gs_free char * name_owner = NULL; - int errsv; + const char * network_path; + NMDeviceIwd * device; + gs_free char * name_owner = NULL; + gs_unref_object GDBusInterface *network = NULL; /* Be paranoid and check the sender address */ name_owner = g_dbus_object_manager_client_get_name_owner( @@ -142,6 +195,25 @@ agent_dbus_method_cb(GDBusConnection * connection, if (!nm_streq0(name_owner, sender)) goto return_error; + if (!strcmp(method_name, "Cancel")) { + const char *reason = NULL; + + g_variant_get(parameters, "(&s)", &reason); + _LOGD("agent-request: Cancel reason: %s", reason); + + if (!priv->last_agent_call_device) + goto return_error; + + if (nm_device_iwd_agent_query(priv->last_agent_call_device, NULL)) { + priv->last_agent_call_device = NULL; + g_dbus_method_invocation_return_value(invocation, NULL); + return; + } + + priv->last_agent_call_device = NULL; + goto return_error; + } + if (!strcmp(method_name, "RequestUserPassword")) g_variant_get(parameters, "(&os)", &network_path, NULL); else @@ -151,47 +223,23 @@ agent_dbus_method_cb(GDBusConnection * connection, network_path, NM_IWD_NETWORK_INTERFACE); if (!network) { - _LOGE("unable to find the network object"); - return; - } - - device_path = get_property_string_or_null(G_DBUS_PROXY(network), "Device"); - if (!device_path) { - _LOGD("agent-request: device not cached for network %s in IWD Agent request", network_path); + _LOGE("agent-request: unable to find the network object"); goto return_error; } - device_obj = g_dbus_object_manager_get_interface(priv->object_manager, - device_path, - NM_IWD_DEVICE_INTERFACE); - - ifname = get_property_string_or_null(G_DBUS_PROXY(device_obj), "Name"); - if (!ifname) { - _LOGD("agent-request: name not cached for device %s in IWD Agent request", device_path); - goto return_error; - } - - ifindex = if_nametoindex(ifname); - if (!ifindex) { - errsv = errno; - _LOGD("agent-request: if_nametoindex failed for Name %s for Device at %s: %i", - ifname, - device_path, - errsv); - goto return_error; - } - - device = nm_manager_get_device_by_ifindex(priv->manager, ifindex); - if (!NM_IS_DEVICE_IWD(device)) { - _LOGD("agent-request: IWD device named %s is not a Wifi device in IWD Agent request", - ifname); + device = get_device_from_network(self, G_DBUS_PROXY(network)); + if (!device) { + _LOGD("agent-request: device not found in IWD Agent request"); goto return_error; } - if (nm_device_iwd_agent_query(NM_DEVICE_IWD(device), invocation)) + if (nm_device_iwd_agent_query(device, invocation)) { + priv->last_agent_call_device = device; return; + } - _LOGD("agent-request: device %s did not handle the IWD Agent request", ifname); + _LOGD("agent-request: device %s did not handle the IWD Agent request", + nm_device_get_iface(NM_DEVICE(device))); return_error: /* IWD doesn't look at the specific error */ @@ -219,10 +267,12 @@ static const GDBusInterfaceInfo iwd_agent_iface_info = NM_DEFINE_GDBUS_INTERFACE NM_DEFINE_GDBUS_ARG_INFO("password", "s"), ), ), NM_DEFINE_GDBUS_METHOD_INFO( "RequestUserPassword", - .in_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("network", "o"), + .in_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("network", "o"), NM_DEFINE_GDBUS_ARG_INFO("user", "s"), ), - .out_args = - NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("password", "s"), ), ), ), ); + .out_args = NM_DEFINE_GDBUS_ARG_INFOS(NM_DEFINE_GDBUS_ARG_INFO("password", "s"), ), ), + NM_DEFINE_GDBUS_METHOD_INFO("Cancel", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("reason", "s"), ), ), ), ); static guint iwd_agent_export(GDBusConnection *connection, gpointer user_data, char **agent_path, GError **error) @@ -259,17 +309,8 @@ register_agent(NMIwdManager *self) GDBusInterface * agent_manager; agent_manager = g_dbus_object_manager_get_interface(priv->object_manager, - "/net/connman/iwd", + "/net/connman/iwd", /* IWD 1.0+ */ NM_IWD_AGENT_MANAGER_INTERFACE); - - if (!agent_manager) { - /* IWD prior to 1.0 dated 30 October, 2019 has the agent manager on a - * different path. */ - agent_manager = g_dbus_object_manager_get_interface(priv->object_manager, - "/", - NM_IWD_AGENT_MANAGER_INTERFACE); - } - if (!agent_manager) { _LOGE("unable to register the IWD Agent: PSK/8021x Wi-Fi networks may not work"); return; @@ -328,7 +369,7 @@ known_network_data_free(KnownNetworkData *network) return; g_object_unref(network->known_network); - mirror_8021x_connection_take_and_delete(network->mirror_connection); + mirror_connection_take_and_delete(network->mirror_connection, network); g_slice_free(KnownNetworkData, network); } @@ -369,14 +410,72 @@ set_device_dbus_object(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *objec nm_device_iwd_set_dbus_object(NM_DEVICE_IWD(device), object); } -/* Look up an existing NMSettingsConnection for a WPA2-Enterprise network - * that has been preprovisioned with an IWD config file, or create a new - * in-memory connection object so that NM autoconnect mechanism and the - * clients know this networks needs no additional EAP configuration from - * the user. +static void +known_network_update_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + gs_unref_variant GVariant *variant = NULL; + gs_free_error GError *error = NULL; + + variant = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!variant) { + nm_log_warn(LOGD_WIFI, + "Updating %s on IWD known network %s failed: %s", + (const char *) user_data, + g_dbus_proxy_get_object_path(G_DBUS_PROXY(source)), + error->message); + } +} + +static void +sett_conn_changed(NMSettingsConnection *sett_conn, guint update_reason, KnownNetworkData *data) +{ + NMSettingsConnectionIntFlags flags; + NMConnection * conn = nm_settings_connection_get_connection(sett_conn); + NMSettingConnection * s_conn = nm_connection_get_setting_connection(conn); + gboolean nm_autoconnectable = nm_setting_connection_get_autoconnect(s_conn); + gboolean iwd_autoconnectable = get_property_bool(data->known_network, "AutoConnect", TRUE); + + nm_assert(sett_conn == data->mirror_connection); + + if (iwd_autoconnectable == nm_autoconnectable) + return; + + /* If this is a generated connection it may be ourselves updating it */ + flags = nm_settings_connection_get_flags(data->mirror_connection); + if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) + return; + + nm_log_dbg(LOGD_WIFI, + "Updating AutoConnect on known network at %s based on connection %s", + g_dbus_proxy_get_object_path(data->known_network), + nm_settings_connection_get_id(data->mirror_connection)); + g_dbus_proxy_call(data->known_network, + DBUS_INTERFACE_PROPERTIES ".Set", + g_variant_new("(ssv)", + NM_IWD_KNOWN_NETWORK_INTERFACE, + "AutoConnect", + g_variant_new_boolean(nm_autoconnectable)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + known_network_update_cb, + "AutoConnect"); +} + +/* Look up an existing NMSettingsConnection for a network that has been + * preprovisioned with an IWD config file or has been connected to before, + * or create a new in-memory NMSettingsConnection object. This will let + * users control the few supported properties (mainly make it + * IWD-autoconnectable or not), remove/forget the network, or, for a + * WPA2-Enterprise type network it will inform the NM autoconnect mechanism + * and the clients that this networks needs no additional EAP configuration + * from the user. */ static NMSettingsConnection * -mirror_8021x_connection(NMIwdManager *self, const char *name, gboolean create_new) +mirror_connection(NMIwdManager * self, + const KnownNetworkId *id, + gboolean create_new, + GDBusProxy * known_network) { NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); NMSettingsConnection *const *iter; @@ -384,43 +483,126 @@ mirror_8021x_connection(NMIwdManager *self, const char *name, gboolean create_ne NMSettingsConnection * settings_connection = NULL; char uuid[37]; NMSetting * setting; - GError * error = NULL; - gs_unref_bytes GBytes *new_ssid = NULL; + gs_free_error GError *error = NULL; + gs_unref_bytes GBytes *new_ssid = NULL; + gsize ssid_len = strlen(id->name); + gboolean autoconnectable = TRUE; + gboolean hidden = FALSE; + gboolean exact_match = TRUE; + const char * key_mgmt = NULL; + + if (known_network) { + autoconnectable = get_property_bool(known_network, "AutoConnect", TRUE); + hidden = get_property_bool(known_network, "Hidden", FALSE); + } for (iter = nm_settings_get_connections(priv->settings, NULL); *iter; iter++) { NMSettingsConnection *sett_conn = *iter; NMConnection * conn = nm_settings_connection_get_connection(sett_conn); NMIwdNetworkSecurity security; - gs_free char * ssid_name = NULL; NMSettingWireless * s_wifi; - NMSetting8021x * s_8021x; - gboolean external = FALSE; - guint i; + const guint8 * ssid_bytes; + gsize ssid_len2; + + if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &security)) + continue; - security = nm_wifi_connection_get_iwd_security(conn, NULL); - if (security != NM_IWD_NETWORK_SECURITY_8021X) + if (security != id->security) continue; s_wifi = nm_connection_get_setting_wireless(conn); if (!s_wifi) continue; - ssid_name = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wifi)); - - if (!nm_streq(ssid_name, name)) + /* The SSID must be UTF-8 if it matches since id->name is known to be + * valid UTF-8, so just memcmp them. + */ + ssid_bytes = g_bytes_get_data(nm_setting_wireless_get_ssid(s_wifi), &ssid_len2); + if (!ssid_bytes || ssid_len2 != ssid_len || memcmp(ssid_bytes, id->name, ssid_len)) continue; - s_8021x = nm_connection_get_setting_802_1x(conn); - for (i = 0; i < nm_setting_802_1x_get_num_eap_methods(s_8021x); i++) { - if (nm_streq(nm_setting_802_1x_get_eap_method(s_8021x, i), "external")) { - external = TRUE; - break; + exact_match = TRUE; + + if (known_network) { + NMSettingConnection *s_conn = nm_connection_get_setting_connection(conn); + + if (nm_setting_connection_get_autoconnect(s_conn) != autoconnectable + || nm_setting_wireless_get_hidden(s_wifi) != hidden) + exact_match = FALSE; + } + + switch (id->security) { + case NM_IWD_NETWORK_SECURITY_WEP: + case NM_IWD_NETWORK_SECURITY_OPEN: + case NM_IWD_NETWORK_SECURITY_PSK: + break; + case NM_IWD_NETWORK_SECURITY_8021X: + { + NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x(conn); + gboolean external = FALSE; + guint i; + + for (i = 0; i < nm_setting_802_1x_get_num_eap_methods(s_8021x); i++) { + if (nm_streq(nm_setting_802_1x_get_eap_method(s_8021x, i), "external")) { + external = TRUE; + break; + } } + + /* Prefer returning connections with EAP method "external" */ + if (!external) + exact_match = FALSE; + } } - /* Prefer returning connections for EAP method "external" */ - if (!settings_connection || external) + if (!settings_connection || exact_match) settings_connection = sett_conn; + + if (exact_match) + break; + } + + if (settings_connection && known_network && !exact_match) { + NMSettingsConnectionIntFlags flags = nm_settings_connection_get_flags(settings_connection); + + /* If we found a connection and it's generated (likely by ourselves) + * it may have been created on a request by + * nm_iwd_manager_get_ap_mirror_connection() when no Known Network + * was available so we didn't have access to its properties other + * than Name and Security. Copy their values to the generated + * NMConnection. + * TODO: avoid notify signals triggering our own watch. + * + * If on the other hand this is a user-created NMConnection we + * should try to copy the properties from it to IWD's Known Network + * using the Properties DBus interface in case the user created an + * NM connection before IWD appeared on the bus, or before IWD + * created its Known Network object. + */ + if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) { + NMConnection *tmp_conn = nm_settings_connection_get_connection(settings_connection); + NMSettingConnection *s_conn = nm_connection_get_setting_connection(tmp_conn); + NMSettingWireless * s_wifi = nm_connection_get_setting_wireless(tmp_conn); + + g_object_set(G_OBJECT(s_conn), + NM_SETTING_CONNECTION_AUTOCONNECT, + autoconnectable, + NULL); + g_object_set(G_OBJECT(s_wifi), NM_SETTING_WIRELESS_HIDDEN, hidden, NULL); + } else { + KnownNetworkData data = {known_network, settings_connection}; + sett_conn_changed(settings_connection, 0, &data); + } + } + + if (settings_connection && known_network) { + /* Reset NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL now that the + * connection is going to be referenced by a known network, we don't + * want it to be deleted when activation fails anymore. + */ + nm_settings_connection_set_flags_full(settings_connection, + NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL, + 0); } /* If we already have an NMSettingsConnection matching this @@ -433,62 +615,86 @@ mirror_8021x_connection(NMIwdManager *self, const char *name, gboolean create_ne connection = nm_simple_connection_new(); - setting = NM_SETTING(g_object_new(NM_TYPE_SETTING_CONNECTION, - NM_SETTING_CONNECTION_TYPE, - NM_SETTING_WIRELESS_SETTING_NAME, - NM_SETTING_CONNECTION_ID, - name, - NM_SETTING_CONNECTION_UUID, - nm_utils_uuid_generate_buf(uuid), - NULL)); + setting = g_object_new(NM_TYPE_SETTING_CONNECTION, + NM_SETTING_CONNECTION_TYPE, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_CONNECTION_ID, + id->name, + NM_SETTING_CONNECTION_UUID, + nm_utils_uuid_generate_buf(uuid), + NM_SETTING_CONNECTION_AUTOCONNECT, + autoconnectable, + NULL); nm_connection_add_setting(connection, setting); - new_ssid = g_bytes_new(name, strlen(name)); - setting = NM_SETTING(g_object_new(NM_TYPE_SETTING_WIRELESS, - NM_SETTING_WIRELESS_SSID, - new_ssid, - NM_SETTING_WIRELESS_MODE, - NM_SETTING_WIRELESS_MODE_INFRA, - NULL)); + new_ssid = g_bytes_new(id->name, ssid_len); + setting = g_object_new(NM_TYPE_SETTING_WIRELESS, + NM_SETTING_WIRELESS_SSID, + new_ssid, + NM_SETTING_WIRELESS_MODE, + NM_SETTING_WIRELESS_MODE_INFRA, + NM_SETTING_WIRELESS_HIDDEN, + hidden, + NULL); nm_connection_add_setting(connection, setting); - setting = NM_SETTING(g_object_new(NM_TYPE_SETTING_WIRELESS_SECURITY, - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, - "open", - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, - "wpa-eap", - NULL)); - nm_connection_add_setting(connection, setting); + switch (id->security) { + case NM_IWD_NETWORK_SECURITY_WEP: + key_mgmt = "none"; + break; + case NM_IWD_NETWORK_SECURITY_OPEN: + key_mgmt = NULL; + break; + case NM_IWD_NETWORK_SECURITY_PSK: + key_mgmt = "wpa-psk"; + break; + case NM_IWD_NETWORK_SECURITY_8021X: + key_mgmt = "wpa-eap"; + break; + } - /* "password" and "private-key-password" may be requested by the IWD agent - * from NM and IWD will implement a specific secret cache policy so by - * default respect that policy and don't save copies of those secrets in - * NM settings. The saved values can not be used anyway because of our - * use of NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW. - */ - setting = NM_SETTING(g_object_new(NM_TYPE_SETTING_802_1X, - NM_SETTING_802_1X_PASSWORD_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, - NM_SETTING_SECRET_FLAG_NOT_SAVED, - NULL)); - nm_setting_802_1x_add_eap_method(NM_SETTING_802_1X(setting), "external"); - nm_connection_add_setting(connection, setting); + if (key_mgmt) { + setting = g_object_new(NM_TYPE_SETTING_WIRELESS_SECURITY, + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "open", + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + key_mgmt, + NULL); + nm_connection_add_setting(connection, setting); + } + + if (id->security == NM_IWD_NETWORK_SECURITY_8021X) { + /* "password" and "private-key-password" may be requested by the IWD agent + * from NM and IWD will implement a specific secret cache policy so by + * default respect that policy and don't save copies of those secrets in + * NM settings. The saved values can not be used anyway because of our + * use of NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW. + */ + setting = g_object_new(NM_TYPE_SETTING_802_1X, + NM_SETTING_802_1X_PASSWORD_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NULL); + nm_setting_802_1x_add_eap_method(NM_SETTING_802_1X(setting), "external"); + nm_connection_add_setting(connection, setting); + } if (!nm_connection_normalize(connection, NULL, NULL, NULL)) return NULL; - if (!nm_settings_add_connection(priv->settings, - connection, - NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, - NM_SETTINGS_CONNECTION_ADD_REASON_NONE, - NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED, - &settings_connection, - &error)) { + if (!nm_settings_add_connection( + priv->settings, + connection, + NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY, + NM_SETTINGS_CONNECTION_ADD_REASON_NONE, + NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED + | (known_network ? 0 : NM_SETTINGS_CONNECTION_INT_FLAGS_EXTERNAL), + &settings_connection, + &error)) { _LOGW("failed to add a mirror NMConnection for IWD's Known Network '%s': %s", - name, + id->name, error->message); - g_error_free(error); return NULL; } @@ -496,7 +702,7 @@ mirror_8021x_connection(NMIwdManager *self, const char *name, gboolean create_ne } static void -mirror_8021x_connection_take_and_delete(NMSettingsConnection *sett_conn) +mirror_connection_take_and_delete(NMSettingsConnection *sett_conn, KnownNetworkData *data) { NMSettingsConnectionIntFlags flags; @@ -510,6 +716,7 @@ mirror_8021x_connection_take_and_delete(NMSettingsConnection *sett_conn) if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) nm_settings_connection_delete(sett_conn, FALSE); + g_signal_handlers_disconnect_by_data(sett_conn, data); g_object_unref(sett_conn); } @@ -539,6 +746,7 @@ interface_added(GDBusObjectManager *object_manager, if (nm_streq(iface_name, NM_IWD_KNOWN_NETWORK_INTERFACE)) { KnownNetworkId * id; + KnownNetworkId * orig_id; KnownNetworkData * data; NMIwdNetworkSecurity security; const char * type_str, *name; @@ -550,7 +758,7 @@ interface_added(GDBusObjectManager *object_manager, return; if (nm_streq(type_str, "open")) - security = NM_IWD_NETWORK_SECURITY_NONE; + security = NM_IWD_NETWORK_SECURITY_OPEN; else if (nm_streq(type_str, "psk")) security = NM_IWD_NETWORK_SECURITY_PSK; else if (nm_streq(type_str, "8021x")) @@ -560,28 +768,42 @@ interface_added(GDBusObjectManager *object_manager, id = known_network_id_new(name, security); - data = g_hash_table_lookup(priv->known_networks, id); - if (data) { + if (g_hash_table_lookup_extended(priv->known_networks, + id, + (void **) &orig_id, + (void **) &data)) { _LOGW("DBus error: KnownNetwork already exists ('%s', %s)", name, type_str); - g_free(id); nm_g_object_ref_set(&data->known_network, proxy); + g_free(id); + id = orig_id; } else { data = g_slice_new0(KnownNetworkData); data->known_network = g_object_ref(proxy); g_hash_table_insert(priv->known_networks, id, data); } - if (security == NM_IWD_NETWORK_SECURITY_8021X) { - sett_conn = mirror_8021x_connection(self, name, TRUE); + sett_conn = mirror_connection(self, id, TRUE, proxy); - if (sett_conn && sett_conn != data->mirror_connection) { - NMSettingsConnection *sett_conn_old = data->mirror_connection; + if (sett_conn && sett_conn != data->mirror_connection) { + NMSettingsConnection *sett_conn_old = data->mirror_connection; - data->mirror_connection = nm_g_object_ref(sett_conn); - mirror_8021x_connection_take_and_delete(sett_conn_old); - } - } else - mirror_8021x_connection_take_and_delete(g_steal_pointer(&data->mirror_connection)); + data->mirror_connection = nm_g_object_ref(sett_conn); + mirror_connection_take_and_delete(sett_conn_old, data); + + g_signal_connect(sett_conn, + NM_SETTINGS_CONNECTION_UPDATED_INTERNAL, + G_CALLBACK(sett_conn_changed), + data); + } + + return; + } + + if (nm_streq(iface_name, NM_IWD_NETWORK_INTERFACE)) { + NMDeviceIwd *device = get_device_from_network(self, proxy); + + if (device) + nm_device_iwd_network_add_remove(device, proxy, TRUE); return; } @@ -618,7 +840,7 @@ interface_removed(GDBusObjectManager *object_manager, return; if (nm_streq(type_str, "open")) - id.security = NM_IWD_NETWORK_SECURITY_NONE; + id.security = NM_IWD_NETWORK_SECURITY_OPEN; else if (nm_streq(type_str, "psk")) id.security = NM_IWD_NETWORK_SECURITY_PSK; else if (nm_streq(type_str, "8021x")) @@ -629,6 +851,15 @@ interface_removed(GDBusObjectManager *object_manager, g_hash_table_remove(priv->known_networks, &id); return; } + + if (nm_streq(iface_name, NM_IWD_NETWORK_INTERFACE)) { + NMDeviceIwd *device = get_device_from_network(self, proxy); + + if (device) + nm_device_iwd_network_add_remove(device, proxy, FALSE); + + return; + } } static void @@ -666,42 +897,47 @@ object_removed(GDBusObjectManager *object_manager, GDBusObject *object, gpointer static void connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer user_data) { - NMIwdManager * self = user_data; - NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); - NMConnection * conn = nm_settings_connection_get_connection(sett_conn); - NMSettingWireless * s_wireless; - gboolean mapped; - KnownNetworkData * data; - KnownNetworkId id; - gs_free char * ssid_str = NULL; - - id.security = nm_wifi_connection_get_iwd_security(conn, &mapped); - if (!mapped) + NMIwdManager * self = user_data; + NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); + NMConnection * conn = nm_settings_connection_get_connection(sett_conn); + NMSettingWireless * s_wireless; + KnownNetworkData * data; + KnownNetworkId id; + char ssid_buf[33]; + const guint8 * ssid_bytes; + gsize ssid_len; + NMSettingsConnection *new_mirror_conn; + + if (!nm_wifi_connection_get_iwd_ssid_and_security(conn, NULL, &id.security)) return; s_wireless = nm_connection_get_setting_wireless(conn); - ssid_str = _nm_utils_ssid_to_utf8(nm_setting_wireless_get_ssid(s_wireless)); - id.name = ssid_str; - data = g_hash_table_lookup(priv->known_networks, &id); - if (!data) + if (!s_wireless) return; - if (id.security == NM_IWD_NETWORK_SECURITY_8021X) { - NMSettingsConnection *new_mirror_conn; + ssid_bytes = g_bytes_get_data(nm_setting_wireless_get_ssid(s_wireless), &ssid_len); + if (!ssid_bytes || ssid_len > 32 || memchr(ssid_bytes, 0, ssid_len)) + return; - if (data->mirror_connection != sett_conn) - return; + memcpy(ssid_buf, ssid_bytes, ssid_len); + ssid_buf[ssid_len] = '\0'; + id.name = ssid_buf; + data = g_hash_table_lookup(priv->known_networks, &id); + if (!data) + return; - g_clear_object(&data->mirror_connection); + if (data->mirror_connection != sett_conn) + return; - /* Don't call Forget for an 8021x network until there's no - * longer *any* matching NMSettingsConnection (debatable) - */ - new_mirror_conn = mirror_8021x_connection(self, id.name, FALSE); - if (new_mirror_conn) { - data->mirror_connection = g_object_ref(new_mirror_conn); - return; - } + g_clear_object(&data->mirror_connection); + + /* Don't call Forget on the Known Network until there's no longer *any* + * matching NMSettingsConnection (debatable) + */ + new_mirror_conn = mirror_connection(self, &id, FALSE, NULL); + if (new_mirror_conn) { + data->mirror_connection = g_object_ref(new_mirror_conn); + return; } if (!priv->running) @@ -801,7 +1037,28 @@ device_added(NMManager *manager, NMDevice *device, gpointer user_data) if (!priv->running) return; + /* Here we handle a potential scenario where IWD's DBus objects for the + * new device popped up before the NMDevice. The + * interface_added/object_added signals have been received already and + * the handlers couldn't do much because the NMDevice wasn't there yet + * so now we go over the Network and Device interfaces again. In this + * exact order for "object path" property consistency -- see reasoning + * in object_compare_interfaces. + */ objects = g_dbus_object_manager_get_objects(priv->object_manager); + + for (iter = objects; iter; iter = iter->next) { + GDBusObject * object = G_DBUS_OBJECT(iter->data); + gs_unref_object GDBusInterface *interface = NULL; + + interface = g_dbus_object_get_interface(object, NM_IWD_NETWORK_INTERFACE); + if (!interface) + continue; + + if (NM_DEVICE_IWD(device) == get_device_from_network(self, (GDBusProxy *) interface)) + nm_device_iwd_network_add_remove(NM_DEVICE_IWD(device), (GDBusProxy *) interface, TRUE); + } + for (iter = objects; iter; iter = iter->next) { GDBusObject * object = G_DBUS_OBJECT(iter->data); gs_unref_object GDBusInterface *interface = NULL; @@ -821,6 +1078,73 @@ device_added(NMManager *manager, NMDevice *device, gpointer user_data) } static void +device_removed(NMManager *manager, NMDevice *device, gpointer user_data) +{ + NMIwdManager * self = user_data; + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + + if (!NM_IS_DEVICE_IWD(device)) + return; + + if (priv->last_agent_call_device == NM_DEVICE_IWD(device)) + priv->last_agent_call_device = NULL; +} + +/* This is used to sort the list of objects returned by GetManagedObjects() + * based on the DBus interfaces available on these objects in such a way that + * the interface_added calls happen in the right order. The order is defined + * by how some DBus interfaces point to interfaces on other objects using + * DBus properties of the type "object path" ("o" signature). This creates + * "dependencies" between objects. + * + * When NM and IWD are running, the InterfacesAdded signals should come in + * an order that ensures consistency of those object paths. For example + * when a Network interface is added with a KnownNetwork property, or that + * property is assigned a new value, the KnownNetwork object pointed to by + * it will have been added in an earlier InterfacesAdded signal. Similarly + * Station.ConnectedNetwork and Station.GetOrdereNetworks() only point to + * existing Network objects. (There may be circular dependencies but during + * initialization we only need a subset of those properties that doesn't + * have this problem.) + * + * But GetManagedObjects doesn't guarantee this kind of consistency so we + * order the returned object list ourselves to simplify the job of + * interface_added(). Objects that don't have any interfaces listed in + * interface_order are moved to the end of the list. + */ +static int +object_compare_interfaces(gconstpointer a, gconstpointer b) +{ + static const char *interface_order[] = { + NM_IWD_KNOWN_NETWORK_INTERFACE, + NM_IWD_NETWORK_INTERFACE, + NM_IWD_DEVICE_INTERFACE, + }; + int rank_a = G_N_ELEMENTS(interface_order); + int rank_b = G_N_ELEMENTS(interface_order); + guint pos; + + for (pos = 0; interface_order[pos]; pos++) { + GDBusInterface *iface_a; + GDBusInterface *iface_b; + + if (rank_a == G_N_ELEMENTS(interface_order) + && (iface_a = g_dbus_object_get_interface(G_DBUS_OBJECT(a), interface_order[pos]))) { + rank_a = pos; + g_object_unref(iface_a); + } + + if (rank_b == G_N_ELEMENTS(interface_order) + && (iface_b = g_dbus_object_get_interface(G_DBUS_OBJECT(b), interface_order[pos]))) { + rank_b = pos; + g_object_unref(iface_b); + } + } + + return rank_a - rank_b; +} + +static void got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) { NMIwdManager * self = user_data; @@ -875,6 +1199,7 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) g_hash_table_remove_all(priv->known_networks); objects = g_dbus_object_manager_get_objects(object_manager); + objects = g_list_sort(objects, object_compare_interfaces); for (iter = objects; iter; iter = iter->next) object_added(NULL, G_DBUS_OBJECT(iter->data), self); @@ -911,6 +1236,47 @@ nm_iwd_manager_is_known_network(NMIwdManager *self, const char *name, NMIwdNetwo return g_hash_table_contains(priv->known_networks, &kn_id); } +NMSettingsConnection * +nm_iwd_manager_get_ap_mirror_connection(NMIwdManager *self, NMWifiAP *ap) +{ + NMIwdManagerPrivate * priv = NM_IWD_MANAGER_GET_PRIVATE(self); + KnownNetworkData * data; + char name_buf[33]; + KnownNetworkId kn_id = {name_buf, NM_IWD_NETWORK_SECURITY_OPEN}; + const guint8 * ssid_bytes; + gsize ssid_len; + NM80211ApFlags flags = nm_wifi_ap_get_flags(ap); + NM80211ApSecurityFlags sec_flags = nm_wifi_ap_get_wpa_flags(ap) | nm_wifi_ap_get_rsn_flags(ap); + + ssid_bytes = g_bytes_get_data(nm_wifi_ap_get_ssid(ap), &ssid_len); + ssid_len = MIN(ssid_len, 32); + memcpy(name_buf, ssid_bytes, ssid_len); + name_buf[ssid_len] = '\0'; + + if (flags & NM_802_11_AP_FLAGS_PRIVACY) + kn_id.security = NM_IWD_NETWORK_SECURITY_WEP; + + if (sec_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK) + kn_id.security = NM_IWD_NETWORK_SECURITY_PSK; + else if (sec_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + kn_id.security = NM_IWD_NETWORK_SECURITY_8021X; + + /* Right now it's easier for us to do a name+security lookup than to use + * the Network.KnownNetwork property to look up by path. + */ + data = g_hash_table_lookup(priv->known_networks, &kn_id); + if (data) + return data->mirror_connection; + + /* We have no KnownNetwork for this AP, we're probably connecting to it for + * the first time. This is not a usual/supported scenario so we don't need + * to bother too much about creating a great mirror connection, we don't + * even have any more information than the Name & Type properties on the + * Network interface. This *should* never happen for an 8021x type network. + */ + return mirror_connection(self, &kn_id, TRUE, NULL); +} + GDBusProxy * nm_iwd_manager_get_dbus_interface(NMIwdManager *self, const char *path, const char *name) { @@ -936,6 +1302,7 @@ nm_iwd_manager_init(NMIwdManager *self) priv->manager = g_object_ref(NM_MANAGER_GET); g_signal_connect(priv->manager, NM_MANAGER_DEVICE_ADDED, G_CALLBACK(device_added), self); + g_signal_connect(priv->manager, NM_MANAGER_DEVICE_REMOVED, G_CALLBACK(device_removed), self); priv->settings = g_object_ref(NM_SETTINGS_GET); g_signal_connect(priv->settings, @@ -978,6 +1345,8 @@ dispose(GObject *object) g_clear_object(&priv->manager); } + priv->last_agent_call_device = NULL; + G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object); } diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/core/devices/wifi/nm-iwd-manager.h index 00f0c304..466f67c7 100644 --- a/src/devices/wifi/nm-iwd-manager.h +++ b/src/core/devices/wifi/nm-iwd-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Intel Corporation */ @@ -8,6 +8,7 @@ #include "devices/nm-device.h" #include "nm-wifi-utils.h" +#include "nm-wifi-ap.h" #define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM #define NM_IWD_SERVICE "net.connman.iwd" @@ -44,6 +45,8 @@ gboolean nm_iwd_manager_is_known_network(NMIwdManager * self, const char * name, NMIwdNetworkSecurity security); +NMSettingsConnection *nm_iwd_manager_get_ap_mirror_connection(NMIwdManager *self, NMWifiAP *ap); + GDBusProxy * nm_iwd_manager_get_dbus_interface(NMIwdManager *self, const char *path, const char *name); diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/core/devices/wifi/nm-wifi-ap.c index 55438a53..08fa10ec 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/core/devices/wifi/nm-wifi-ap.c @@ -1,14 +1,15 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-ap.h" #include <stdlib.h> +#include <linux/if_ether.h> #include "NetworkManagerUtils.h" #include "devices/nm-device.h" @@ -83,29 +84,6 @@ nm_wifi_ap_get_ssid(const NMWifiAP *ap) } gboolean -nm_wifi_ap_set_ssid_arr(NMWifiAP *ap, const guint8 *ssid, gsize ssid_len) -{ - NMWifiAPPrivate *priv; - - g_return_val_if_fail(NM_IS_WIFI_AP(ap), FALSE); - - if (ssid_len > 32) - g_return_val_if_reached(FALSE); - - priv = NM_WIFI_AP_GET_PRIVATE(ap); - - if (nm_utils_gbytes_equal_mem(priv->ssid, ssid, ssid_len)) - return FALSE; - - nm_clear_pointer(&priv->ssid, g_bytes_unref); - if (ssid_len > 0) - priv->ssid = g_bytes_new(ssid, ssid_len); - - _notify(ap, PROP_SSID); - return TRUE; -} - -gboolean nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid) { NMWifiAPPrivate *priv; @@ -185,11 +163,13 @@ nm_wifi_ap_get_address(const NMWifiAP *ap) return NM_WIFI_AP_GET_PRIVATE(ap)->address; } -static gboolean -nm_wifi_ap_set_address_bin(NMWifiAP *ap, const guint8 addr[static 6 /* ETH_ALEN */]) +gboolean +nm_wifi_ap_set_address_bin(NMWifiAP *ap, const NMEtherAddr *addr) { NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE(ap); + nm_assert(addr); + if (!priv->address || !nm_utils_hwaddr_matches(addr, ETH_ALEN, priv->address, -1)) { g_free(priv->address); priv->address = nm_utils_hwaddr_ntoa(addr, ETH_ALEN); @@ -202,13 +182,13 @@ nm_wifi_ap_set_address_bin(NMWifiAP *ap, const guint8 addr[static 6 /* ETH_ALEN gboolean nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr) { - guint8 addr_buf[ETH_ALEN]; + NMEtherAddr addr_buf; g_return_val_if_fail(NM_IS_WIFI_AP(ap), FALSE); - if (!addr || !nm_utils_hwaddr_aton(addr, addr_buf, sizeof(addr_buf))) + if (!addr || !nm_utils_hwaddr_aton(addr, &addr_buf, sizeof(addr_buf))) g_return_val_if_reached(FALSE); - return nm_wifi_ap_set_address_bin(ap, addr_buf); + return nm_wifi_ap_set_address_bin(ap, &addr_buf); } NM80211Mode @@ -365,6 +345,18 @@ nm_wifi_ap_get_metered(const NMWifiAP *self) return NM_WIFI_AP_GET_PRIVATE(self)->metered; } +NM80211ApSecurityFlags +nm_wifi_ap_get_wpa_flags(const NMWifiAP *self) +{ + return NM_WIFI_AP_GET_PRIVATE(self)->wpa_flags; +} + +NM80211ApSecurityFlags +nm_wifi_ap_get_rsn_flags(const NMWifiAP *self) +{ + return NM_WIFI_AP_GET_PRIVATE(self)->rsn_flags; +} + /*****************************************************************************/ gboolean @@ -395,7 +387,7 @@ nm_wifi_ap_update_from_properties(NMWifiAP *ap, const NMSupplicantBssInfo *bss_i changed |= nm_wifi_ap_set_ssid(ap, bss_info->ssid); if (bss_info->bssid_valid) - changed |= nm_wifi_ap_set_address_bin(ap, bss_info->bssid); + changed |= nm_wifi_ap_set_address_bin(ap, &bss_info->bssid); else { /* we don't actually clear the value. */ } @@ -523,7 +515,7 @@ nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64 g_snprintf(str_buf, buf_len, - "%17s %-35s [ %c %3u %3u%% %c%c W:%04X R:%04X ] %s sup:%s [nm:%s]", + "%17s %-35s [ %c %3u %3u%% %c%c %c%c W:%04X R:%04X ] %s sup:%s [nm:%s]", priv->address ?: "(none)", (ssid_to_free = _nm_utils_ssid_to_string(priv->ssid)), (priv->mode == NM_802_11_MODE_ADHOC @@ -535,6 +527,10 @@ nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64 priv->strength, priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_', priv->metered ? 'M' : '_', + priv->flags & NM_802_11_AP_FLAGS_WPS ? 'W' : '_', + priv->flags & NM_802_11_AP_FLAGS_WPS_PIN + ? 'p' + : (priv->flags & NM_802_11_AP_FLAGS_WPS_PBC ? '#' : '_'), priv->wpa_flags & 0xFFFF, priv->rsn_flags & 0xFFFF, priv->last_seen_msec != G_MININT64 @@ -751,7 +747,7 @@ nm_wifi_ap_new_fake_from_connection(NMConnection *connection) s_wireless = nm_connection_get_setting_wireless(connection); g_return_val_if_fail(s_wireless != NULL, NULL); - ap = (NMWifiAP *) g_object_new(NM_TYPE_WIFI_AP, NULL); + ap = g_object_new(NM_TYPE_WIFI_AP, NULL); priv = NM_WIFI_AP_GET_PRIVATE(ap); priv->fake = TRUE; @@ -803,8 +799,8 @@ nm_wifi_ap_new_fake_from_connection(NMConnection *connection) if (!strcmp(key_mgmt, "none") || !strcmp(key_mgmt, "ieee8021x")) goto done; - psk = !strcmp(key_mgmt, "wpa-psk"); - eap = !strcmp(key_mgmt, "wpa-eap"); + psk = nm_streq(key_mgmt, "wpa-psk"); + eap = nm_streq(key_mgmt, "wpa-eap") || nm_streq(key_mgmt, "wpa-eap-suite-b-192"); if (!adhoc && (psk || eap)) { if (has_proto(s_wireless_sec, PROTO_WPA)) { flags = priv->wpa_flags @@ -897,7 +893,7 @@ nm_wifi_ap_class_init(NMWifiAPClass *ap_class) | NM_802_11_AP_SEC_GROUP_WEP104 | NM_802_11_AP_SEC_GROUP_TKIP | NM_802_11_AP_SEC_GROUP_CCMP \ | NM_802_11_AP_SEC_KEY_MGMT_PSK | NM_802_11_AP_SEC_KEY_MGMT_802_1X \ | NM_802_11_AP_SEC_KEY_MGMT_SAE | NM_802_11_AP_SEC_KEY_MGMT_OWE \ - | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM) + | NM_802_11_AP_SEC_KEY_MGMT_OWE_TM | NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192) GObjectClass * object_class = G_OBJECT_CLASS(ap_class); NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS(ap_class); diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/core/devices/wifi/nm-wifi-ap.h index 4608c6ff..bdd72415 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/core/devices/wifi/nm-wifi-ap.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -64,23 +64,25 @@ nm_wifi_ap_get_supplicant_path(NMWifiAP *ap) return ap->_supplicant_path; } -GBytes * nm_wifi_ap_get_ssid(const NMWifiAP *ap); -gboolean nm_wifi_ap_set_ssid_arr(NMWifiAP *ap, const guint8 *ssid, gsize ssid_len); -gboolean nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid); -const char * nm_wifi_ap_get_address(const NMWifiAP *ap); -gboolean nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr); -NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap); -gboolean nm_wifi_ap_is_hotspot(NMWifiAP *ap); -gint8 nm_wifi_ap_get_strength(NMWifiAP *ap); -gboolean nm_wifi_ap_set_strength(NMWifiAP *ap, gint8 strength); -guint32 nm_wifi_ap_get_freq(NMWifiAP *ap); -gboolean nm_wifi_ap_set_freq(NMWifiAP *ap, guint32 freq); -guint32 nm_wifi_ap_get_max_bitrate(NMWifiAP *ap); -gboolean nm_wifi_ap_set_max_bitrate(NMWifiAP *ap, guint32 bitrate); -gboolean nm_wifi_ap_get_fake(const NMWifiAP *ap); -gboolean nm_wifi_ap_set_fake(NMWifiAP *ap, gboolean fake); -NM80211ApFlags nm_wifi_ap_get_flags(const NMWifiAP *self); -gboolean nm_wifi_ap_get_metered(const NMWifiAP *self); +GBytes * nm_wifi_ap_get_ssid(const NMWifiAP *ap); +gboolean nm_wifi_ap_set_ssid(NMWifiAP *ap, GBytes *ssid); +const char * nm_wifi_ap_get_address(const NMWifiAP *ap); +gboolean nm_wifi_ap_set_address(NMWifiAP *ap, const char *addr); +gboolean nm_wifi_ap_set_address_bin(NMWifiAP *ap, const NMEtherAddr *addr); +NM80211Mode nm_wifi_ap_get_mode(NMWifiAP *ap); +gboolean nm_wifi_ap_is_hotspot(NMWifiAP *ap); +gint8 nm_wifi_ap_get_strength(NMWifiAP *ap); +gboolean nm_wifi_ap_set_strength(NMWifiAP *ap, gint8 strength); +guint32 nm_wifi_ap_get_freq(NMWifiAP *ap); +gboolean nm_wifi_ap_set_freq(NMWifiAP *ap, guint32 freq); +guint32 nm_wifi_ap_get_max_bitrate(NMWifiAP *ap); +gboolean nm_wifi_ap_set_max_bitrate(NMWifiAP *ap, guint32 bitrate); +gboolean nm_wifi_ap_get_fake(const NMWifiAP *ap); +gboolean nm_wifi_ap_set_fake(NMWifiAP *ap, gboolean fake); +NM80211ApFlags nm_wifi_ap_get_flags(const NMWifiAP *self); +gboolean nm_wifi_ap_get_metered(const NMWifiAP *self); +NM80211ApSecurityFlags nm_wifi_ap_get_wpa_flags(const NMWifiAP *self); +NM80211ApSecurityFlags nm_wifi_ap_get_rsn_flags(const NMWifiAP *self); const char * nm_wifi_ap_to_string(const NMWifiAP *self, char *str_buf, gulong buf_len, gint64 now_msec); diff --git a/src/devices/wifi/nm-wifi-common.c b/src/core/devices/wifi/nm-wifi-common.c index e2ef4186..c715c07c 100644 --- a/src/devices/wifi/nm-wifi-common.c +++ b/src/core/devices/wifi/nm-wifi-common.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-common.h" diff --git a/src/devices/wifi/nm-wifi-common.h b/src/core/devices/wifi/nm-wifi-common.h index 203f2a53..fd6f47ed 100644 --- a/src/devices/wifi/nm-wifi-common.h +++ b/src/core/devices/wifi/nm-wifi-common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/core/devices/wifi/nm-wifi-factory.c index 1d140759..40375e1c 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/core/devices/wifi/nm-wifi-factory.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <gmodule.h> @@ -52,7 +52,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES( G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { - return (NMDeviceFactory *) g_object_new(NM_TYPE_WIFI_FACTORY, NULL); + return g_object_new(NM_TYPE_WIFI_FACTORY, NULL); } /*****************************************************************************/ diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/core/devices/wifi/nm-wifi-p2p-peer.c index a194f168..8488f32d 100644 --- a/src/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.c @@ -1,13 +1,14 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-p2p-peer.h" #include <stdlib.h> +#include <linux/if_ether.h> #include "NetworkManagerUtils.h" #include "devices/nm-device.h" @@ -407,7 +408,7 @@ nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer *peer, const NMSupplicantP /* We currently only use the groups information internally to check if * the peer is still joined. */ - if (!_nm_utils_strv_equal((char **) priv->groups, (char **) peer_info->groups)) { + if (!nm_utils_strv_equal(priv->groups, peer_info->groups)) { g_free(priv->groups); priv->groups = nm_utils_strv_dup_packed(peer_info->groups, -1); changed |= TRUE; diff --git a/src/devices/wifi/nm-wifi-p2p-peer.h b/src/core/devices/wifi/nm-wifi-p2p-peer.h index e19cf3d8..ee4bfb53 100644 --- a/src/devices/wifi/nm-wifi-p2p-peer.h +++ b/src/core/devices/wifi/nm-wifi-p2p-peer.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index e371d197..aed236cc 100644 --- a/src/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-utils.h" @@ -407,7 +407,7 @@ verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, auth_alg = nm_setting_wireless_security_get_auth_alg(s_wsec); if (key_mgmt) { - if (!strcmp(key_mgmt, "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192")) { if (!s_8021x) { g_set_error_literal(error, NM_CONNECTION_ERROR, @@ -444,7 +444,8 @@ verify_wpa_eap(NMSettingWirelessSecurity *s_wsec, if (is_wpa_eap || s_8021x) { /* Make sure the AP's capabilities support WPA-EAP */ if (!(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) - && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)) { + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X) + && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { g_set_error_literal(error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, @@ -838,6 +839,14 @@ nm_wifi_utils_complete_connection(GBytes * ap_ssid, /* Leave proto/pairwise/group as client set them; if they are unset the * supplicant will figure out the best combination at connect time. */ + } else if ((key_mgmt && !strcmp(key_mgmt, "wpa-eap-suite-b-192")) + || (ap_rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192)) { + g_object_set(s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + "wpa-eap-suite-b-192", + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + "open", + NULL); } else { g_set_error_literal(error, NM_CONNECTION_ERROR, @@ -886,34 +895,51 @@ nm_wifi_utils_is_manf_default_ssid(GBytes *ssid) return FALSE; } -NMIwdNetworkSecurity -nm_wifi_connection_get_iwd_security(NMConnection *connection, gboolean *mapped) +/* To be used for connections where the SSID has been validated before */ +gboolean +nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, + char ** ssid, + NMIwdNetworkSecurity *security) { + NMSettingWireless * s_wireless; NMSettingWirelessSecurity *s_wireless_sec; const char * key_mgmt = NULL; - if (!nm_connection_get_setting_wireless(connection)) - goto error; + s_wireless = nm_connection_get_setting_wireless(connection); + if (!s_wireless) + return FALSE; + + if (ssid) { + GBytes * bytes = nm_setting_wireless_get_ssid(s_wireless); + gsize ssid_len; + const char *ssid_str = (const char *) g_bytes_get_data(bytes, &ssid_len); - NM_SET_OUT(mapped, TRUE); + nm_assert(bytes && g_utf8_validate(ssid_str, ssid_len, NULL)); + NM_SET_OUT(ssid, g_strndup(ssid_str, ssid_len)); + } + + if (!security) + return TRUE; s_wireless_sec = nm_connection_get_setting_wireless_security(connection); - if (!s_wireless_sec) - return NM_IWD_NETWORK_SECURITY_NONE; + if (!s_wireless_sec) { + NM_SET_OUT(security, NM_IWD_NETWORK_SECURITY_OPEN); + return TRUE; + } key_mgmt = nm_setting_wireless_security_get_key_mgmt(s_wireless_sec); nm_assert(key_mgmt); if (NM_IN_STRSET(key_mgmt, "none", "ieee8021x")) - return NM_IWD_NETWORK_SECURITY_WEP; - - if (nm_streq(key_mgmt, "wpa-psk")) - return NM_IWD_NETWORK_SECURITY_PSK; - - if (nm_streq(key_mgmt, "wpa-eap")) - return NM_IWD_NETWORK_SECURITY_8021X; + NM_SET_OUT(security, NM_IWD_NETWORK_SECURITY_WEP); + else if (nm_streq(key_mgmt, "owe")) + NM_SET_OUT(security, NM_IWD_NETWORK_SECURITY_OPEN); + else if (NM_IN_STRSET(key_mgmt, "wpa-psk", "sae")) + NM_SET_OUT(security, NM_IWD_NETWORK_SECURITY_PSK); + else if (nm_streq(key_mgmt, "wpa-eap")) + NM_SET_OUT(security, NM_IWD_NETWORK_SECURITY_8021X); + else + return FALSE; -error: - NM_SET_OUT(mapped, FALSE); - return NM_IWD_NETWORK_SECURITY_NONE; + return TRUE; } diff --git a/src/devices/wifi/nm-wifi-utils.h b/src/core/devices/wifi/nm-wifi-utils.h index 678b353b..474bea41 100644 --- a/src/devices/wifi/nm-wifi-utils.h +++ b/src/core/devices/wifi/nm-wifi-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ @@ -13,7 +13,7 @@ #include "nm-setting-8021x.h" typedef enum { - NM_IWD_NETWORK_SECURITY_NONE, + NM_IWD_NETWORK_SECURITY_OPEN, NM_IWD_NETWORK_SECURITY_WEP, NM_IWD_NETWORK_SECURITY_PSK, NM_IWD_NETWORK_SECURITY_8021X, @@ -32,7 +32,8 @@ gboolean nm_wifi_utils_complete_connection(GBytes * ssid, gboolean nm_wifi_utils_is_manf_default_ssid(GBytes *ssid); -NMIwdNetworkSecurity nm_wifi_connection_get_iwd_security(NMConnection *connection, - gboolean * mapped); +gboolean nm_wifi_connection_get_iwd_ssid_and_security(NMConnection * connection, + char ** ssid, + NMIwdNetworkSecurity *security); #endif /* __NM_WIFI_UTILS_H__ */ diff --git a/src/devices/wifi/tests/test-devices-wifi.c b/src/core/devices/wifi/tests/test-devices-wifi.c index 7be55860..bc0ba126 100644 --- a/src/devices/wifi/tests/test-devices-wifi.c +++ b/src/core/devices/wifi/tests/test-devices-wifi.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "devices/wifi/nm-wifi-utils.h" #include "devices/wifi/nm-device-wifi.h" diff --git a/src/devices/wwan/libnm-wwan.ver b/src/core/devices/wwan/libnm-wwan.ver index c368a590..c368a590 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/core/devices/wwan/libnm-wwan.ver diff --git a/src/devices/wwan/meson.build b/src/core/devices/wwan/meson.build index 97252edc..87af0429 100644 --- a/src/devices/wwan/meson.build +++ b/src/core/devices/wwan/meson.build @@ -1,29 +1,22 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later -nm_service_providers_source = files('nm-service-providers.c') - -sources = nm_service_providers_source + files( - 'nm-modem-broadband.c', - 'nm-modem.c', - 'nm-modem-manager.c', -) - -deps = [ - daemon_nm_default_dep, - libsystemd_dep, - mm_glib_dep, -] - -if enable_ofono - sources += files('nm-modem-ofono.c') -endif +wwan_inc = include_directories('.') linker_script = join_paths(meson.current_source_dir(), 'libnm-wwan.ver') libnm_wwan = shared_module( 'nm-wwan', - sources: sources, - dependencies: deps, + sources: files( + 'nm-service-providers.c', + 'nm-modem-broadband.c', + 'nm-modem.c', + 'nm-modem-manager.c', + ) + (enable_ofono ? files('nm-modem-ofono.c') : files()), + dependencies: [ + core_plugin_dep, + libsystemd_dep, + mm_glib_dep, + ], c_args: daemon_c_flags, link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, @@ -31,8 +24,6 @@ libnm_wwan = shared_module( install_dir: nm_plugindir, ) -wwan_inc = include_directories('.') - libnm_wwan_dep = declare_dependency( include_directories: wwan_inc, link_with: libnm_wwan, @@ -43,18 +34,23 @@ core_plugins += libnm_wwan test( 'check-wwan', check_exports, - args: [libnm_wwan.full_path(), linker_script], -) - -sources = files( - 'nm-device-modem.c', - 'nm-wwan-factory.c', + args: [ + libnm_wwan.full_path(), + linker_script, + ], ) libnm_device_plugin_wwan = shared_module( 'nm-device-plugin-wwan', - sources: sources, - dependencies: deps, + sources: files( + 'nm-device-modem.c', + 'nm-wwan-factory.c', + ), + dependencies: [ + core_plugin_dep, + libsystemd_dep, + mm_glib_dep, + ], c_args: daemon_c_flags, link_with: libnm_wwan, link_args: ldflags_linker_script_devices, @@ -73,18 +69,18 @@ run_target( ) if enable_tests - test_unit = 'test-service-providers' - exe = executable( - test_unit, - ['tests/' + test_unit + '.c'] + nm_service_providers_source, + 'test-service-providers', + files( + 'tests/test-service-providers.c', + 'nm-service-providers.c', + ), include_directories: wwan_inc, - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) - test( - 'wwan/' + test_unit, + 'wwan/test-service-providers', test_script, timeout: default_test_timeout, args: test_args + [exe.full_path()], diff --git a/src/devices/wwan/nm-device-modem.c b/src/core/devices/wwan/nm-device-modem.c index f77de85a..3ea89d2c 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/core/devices/wwan/nm-device-modem.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-device-modem.h" @@ -16,8 +16,8 @@ #include "NetworkManagerUtils.h" #include "nm-core-internal.h" +#define _NMLOG_DEVICE_TYPE NMDeviceModem #include "devices/nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceModem); /*****************************************************************************/ diff --git a/src/devices/wwan/nm-device-modem.h b/src/core/devices/wwan/nm-device-modem.h index caabeb6c..f171d76f 100644 --- a/src/devices/wwan/nm-device-modem.h +++ b/src/core/devices/wwan/nm-device-modem.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/core/devices/wwan/nm-modem-broadband.c index 7b3a13a3..ca028804 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/core/devices/wwan/nm-modem-broadband.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Aleksander Morgado <aleksander@gnu.org> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-modem-broadband.h" #include "nm-service-providers.h" diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/core/devices/wwan/nm-modem-broadband.h index 5a822f6f..627fe25a 100644 --- a/src/devices/wwan/nm-modem-broadband.h +++ b/src/core/devices/wwan/nm-modem-broadband.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - Aleksander Morgado <aleksander@gnu.org> */ diff --git a/src/devices/wwan/nm-modem-manager.c b/src/core/devices/wwan/nm-modem-manager.c index 65f7c9f9..598c6898 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/core/devices/wwan/nm-modem-manager.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. * Copyright (C) 2009 - 2013 Canonical Ltd. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-modem-manager.h" diff --git a/src/devices/wwan/nm-modem-manager.h b/src/core/devices/wwan/nm-modem-manager.h index 895d4ced..e89a032b 100644 --- a/src/devices/wwan/nm-modem-manager.h +++ b/src/core/devices/wwan/nm-modem-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. diff --git a/src/devices/wwan/nm-modem-ofono.c b/src/core/devices/wwan/nm-modem-ofono.c index d8d0893b..21734cee 100644 --- a/src/devices/wwan/nm-modem-ofono.c +++ b/src/core/devices/wwan/nm-modem-ofono.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2016 Canonical Ltd. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-modem-ofono.h" @@ -1160,20 +1160,20 @@ nm_modem_ofono_new(const char *path) */ basename = g_path_get_basename(path); - return (NMModem *) g_object_new(NM_TYPE_MODEM_OFONO, - NM_MODEM_PATH, - path, - NM_MODEM_UID, - basename, - NM_MODEM_DEVICE_ID, - basename, - NM_MODEM_CONTROL_PORT, - "ofono", /* mandatory */ - NM_MODEM_DRIVER, - "ofono", - NM_MODEM_STATE, - (int) NM_MODEM_STATE_INITIALIZING, - NULL); + return g_object_new(NM_TYPE_MODEM_OFONO, + NM_MODEM_PATH, + path, + NM_MODEM_UID, + basename, + NM_MODEM_DEVICE_ID, + basename, + NM_MODEM_CONTROL_PORT, + "ofono", /* mandatory */ + NM_MODEM_DRIVER, + "ofono", + NM_MODEM_STATE, + (int) NM_MODEM_STATE_INITIALIZING, + NULL); } static void diff --git a/src/devices/wwan/nm-modem-ofono.h b/src/core/devices/wwan/nm-modem-ofono.h index 10b4a385..260e3954 100644 --- a/src/devices/wwan/nm-modem-ofono.h +++ b/src/core/devices/wwan/nm-modem-ofono.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - Canonical Ltd. */ diff --git a/src/devices/wwan/nm-modem.c b/src/core/devices/wwan/nm-modem.c index 9e16420e..0d334fa4 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/core/devices/wwan/nm-modem.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2014 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-modem.h" diff --git a/src/devices/wwan/nm-modem.h b/src/core/devices/wwan/nm-modem.h index 4b275cf7..87162cfc 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/core/devices/wwan/nm-modem.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2011 Red Hat, Inc. * Copyright (C) 2009 Novell, Inc. diff --git a/src/devices/wwan/nm-service-providers.c b/src/core/devices/wwan/nm-service-providers.c index f7c6b5b8..89add6c5 100644 --- a/src/devices/wwan/nm-service-providers.c +++ b/src/core/devices/wwan/nm-service-providers.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2009 Novell, Inc. * Author: Tambet Ingo (tambet@gmail.com). @@ -6,7 +6,7 @@ * Copyright (C) 2012 Lanedo GmbH */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-service-providers.h" diff --git a/src/devices/wwan/nm-service-providers.h b/src/core/devices/wwan/nm-service-providers.h index 093bcd5b..959f660a 100644 --- a/src/devices/wwan/nm-service-providers.h +++ b/src/core/devices/wwan/nm-service-providers.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/core/devices/wwan/nm-wwan-factory.c index 1c3406da..5d2ce2b3 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/core/devices/wwan/nm-wwan-factory.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <gmodule.h> @@ -54,7 +54,7 @@ NM_DEVICE_FACTORY_DECLARE_TYPES(NM_DEVICE_FACTORY_DECLARE_LINK_TYPES( G_MODULE_EXPORT NMDeviceFactory * nm_device_factory_create(GError **error) { - return (NMDeviceFactory *) g_object_new(NM_TYPE_WWAN_FACTORY, NULL); + return g_object_new(NM_TYPE_WWAN_FACTORY, NULL); } /*****************************************************************************/ diff --git a/src/devices/wwan/tests/test-service-providers.c b/src/core/devices/wwan/tests/test-service-providers.c index ec19d588..f95cccf8 100644 --- a/src/devices/wwan/tests/test-service-providers.c +++ b/src/core/devices/wwan/tests/test-service-providers.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-service-providers.h" @@ -43,7 +43,7 @@ test_positive(void) GMainLoop *loop = g_main_loop_new(NULL, FALSE); nm_service_providers_find_gsm_apn(NM_BUILD_SRCDIR - "/src/devices/wwan/tests/test-service-providers.xml", + "/src/core/devices/wwan/tests/test-service-providers.xml", "13337", NULL, test_positive_cb, @@ -76,7 +76,7 @@ test_negative(void) GMainLoop *loop = g_main_loop_new(NULL, FALSE); nm_service_providers_find_gsm_apn(NM_BUILD_SRCDIR - "/src/devices/wwan/tests/test-service-providers.xml", + "/src/core/devices/wwan/tests/test-service-providers.xml", "78130", NULL, test_negative_cb, diff --git a/src/devices/wwan/tests/test-service-providers.xml b/src/core/devices/wwan/tests/test-service-providers.xml index f0ca2deb..f0ca2deb 100644 --- a/src/devices/wwan/tests/test-service-providers.xml +++ b/src/core/devices/wwan/tests/test-service-providers.xml diff --git a/src/core/dhcp/meson.build b/src/core/dhcp/meson.build new file mode 100644 index 00000000..1bb004cd --- /dev/null +++ b/src/core/dhcp/meson.build @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +executable( + 'nm-dhcp-helper', + 'nm-dhcp-helper.c', + dependencies: glib_nm_default_dep, + c_args: [ + '-DG_LOG_DOMAIN="nm-dhcp-helper"', + ], + link_args: ldflags_linker_script_binary, + link_depends: linker_script_binary, + install: true, + install_dir: nm_libexecdir, +) + +if enable_tests + subdir('tests') +endif diff --git a/src/dhcp/nm-dhcp-client-logging.h b/src/core/dhcp/nm-dhcp-client-logging.h index ecbf5210..d69b3ebd 100644 --- a/src/dhcp/nm-dhcp-client-logging.h +++ b/src/core/dhcp/nm-dhcp-client-logging.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 46ab4895..c38c814e 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-client.h" @@ -20,6 +20,7 @@ #include "NetworkManagerUtils.h" #include "nm-utils.h" #include "nm-dhcp-utils.h" +#include "nm-dhcp-options.h" #include "platform/nm-platform.h" #include "nm-dhcp-client-logging.h" @@ -367,10 +368,13 @@ reason_to_state(NMDhcpClient *self, const char *iface, const char *reason) else if (g_ascii_strcasecmp(reason, "nak") == 0 || g_ascii_strcasecmp(reason, "expire") == 0 || g_ascii_strcasecmp(reason, "expire6") == 0) return NM_DHCP_STATE_EXPIRE; - else if (g_ascii_strcasecmp(reason, "end") == 0) + else if (g_ascii_strcasecmp(reason, "end") == 0 || g_ascii_strcasecmp(reason, "stop") == 0 + || g_ascii_strcasecmp(reason, "stopped") == 0) return NM_DHCP_STATE_DONE; else if (g_ascii_strcasecmp(reason, "fail") == 0 || g_ascii_strcasecmp(reason, "abend") == 0) return NM_DHCP_STATE_FAIL; + else if (g_ascii_strcasecmp(reason, "preinit") == 0) + return NM_DHCP_STATE_NOOP; _LOGD("unmapped DHCP state '%s'", reason); return NM_DHCP_STATE_UNKNOWN; @@ -434,8 +438,7 @@ nm_dhcp_client_set_state(NMDhcpClient *self, NMIPConfig * ip_config, GHashTable * options) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - gs_free char * event_id = NULL; + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(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)); @@ -459,23 +462,36 @@ nm_dhcp_client_set_state(NMDhcpClient *self, && !NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) return; - if (_LOGI_ENABLED()) { + if (_LOGD_ENABLED()) { gs_free const char **keys = NULL; guint i, nkeys; keys = nm_utils_strdict_get_keys(options, TRUE, &nkeys); for (i = 0; i < nkeys; i++) { - _LOGI("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i])); + _LOGD("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i])); } } - if (priv->addr_family == AF_INET6) + if (_LOGT_ENABLED() && 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); + } - _LOGI("state changed %s -> %s%s%s%s", - state_to_string(priv->state), - state_to_string(new_state), - NM_PRINT_FMT_QUOTED(event_id, ", event ID=\"", 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); + const char *addr = nm_g_hash_table_lookup(options, req_str); + + _LOGI("state changed %s -> %s%s%s%s", + state_to_string(priv->state), + state_to_string(new_state), + NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", "")); + } priv->state = new_state; g_signal_emit(G_OBJECT(self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, options); @@ -547,6 +563,18 @@ nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid) priv->watch_id = g_child_watch_add(pid, daemon_watch_cb, self); } +void +nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + + g_return_if_fail(priv->pid == pid); + priv->pid = -1; + + watch_cleanup(self); + timeout_cleanup(self); +} + gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GBytes * client_id, @@ -874,6 +902,9 @@ nm_dhcp_client_handle_event(gpointer unused, state_to_string(new_state), reason); + if (new_state == NM_DHCP_STATE_NOOP) + return TRUE; + if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) { GVariantIter iter; const char * name; diff --git a/src/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 05faa9ea..72ab477d 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -55,6 +55,7 @@ typedef enum { NM_DHCP_STATE_EXPIRE, /* lease expired or NAKed */ NM_DHCP_STATE_FAIL, /* failed for some reason */ NM_DHCP_STATE_TERMINATED, /* client is no longer running */ + NM_DHCP_STATE_NOOP, /* state is a non operation for NetworkManager */ __NM_DHCP_STATE_MAX, NM_DHCP_STATE_MAX = __NM_DHCP_STATE_MAX - 1, } NMDhcpState; @@ -183,6 +184,8 @@ void nm_dhcp_client_start_timeout(NMDhcpClient *self); 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, diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c index f0eed6f5..ad1e097f 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c @@ -1,15 +1,16 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-dhclient-utils.h" #include <ctype.h> #include <arpa/inet.h> #include <net/if.h> +#include <linux/if_ether.h> #include "nm-glib-aux/nm-dedup-multi.h" diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/core/dhcp/nm-dhcp-dhclient-utils.h index 3e524ee0..ed7c1c7c 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/core/dhcp/nm-dhcp-dhclient-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c index 260f400e..c42a0ba5 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/core/dhcp/nm-dhcp-dhclient.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2012 Red Hat, Inc. */ @@ -10,7 +10,7 @@ #include <time.h> #undef _XOPEN_SOURCE -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #if WITH_DHCLIENT @@ -437,6 +437,12 @@ dhclient_start(NMDhcpClient *client, if (addr_family == AF_INET6) { g_ptr_array_add(argv, (gpointer) "-6"); + + if (prefixes > 0 && nm_streq0(mode_opt, "-S")) { + /* -S is incompatible with -P, only use the latter */ + mode_opt = NULL; + } + if (mode_opt) g_ptr_array_add(argv, (gpointer) mode_opt); while (prefixes--) diff --git a/src/dhcp/nm-dhcp-dhcpcanon.c b/src/core/dhcp/nm-dhcp-dhcpcanon.c index 8e61b6e5..3504a048 100644 --- a/src/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/core/dhcp/nm-dhcp-dhcpcanon.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 juga <juga at riseup dot net> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #if WITH_DHCPCANON diff --git a/src/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c index b2b5d28b..cf9fe5c2 100644 --- a/src/dhcp/nm-dhcp-dhcpcd.c +++ b/src/core/dhcp/nm-dhcp-dhcpcd.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* - * Copyright (C) 2008 Roy Marples + * Copyright (C) 2008,2020 Roy Marples <roy@marples.name> * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #if WITH_DHCPCD @@ -40,7 +40,6 @@ static GType nm_dhcp_dhcpcd_get_type(void); /*****************************************************************************/ typedef struct { - char * pid_file; NMDhcpListener *dhcp_listener; } NMDhcpDhcpcdPrivate; @@ -71,39 +70,37 @@ ip4_start(NMDhcpClient *client, const char * last_ip4_address, GError ** error) { - NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(self); - gs_unref_ptrarray GPtrArray *argv = NULL; - pid_t pid = -1; - GError * local = NULL; - gs_free char * cmd_str = NULL; - gs_free char * binary_name = NULL; + NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); + gs_unref_ptrarray GPtrArray *argv = NULL; + pid_t pid; + GError * local; + gs_free char * cmd_str = NULL; const char * iface; const char * dhcpcd_path; const char * hostname; - g_return_val_if_fail(priv->pid_file == NULL, FALSE); + pid = nm_dhcp_client_get_pid(client); + g_return_val_if_fail(pid == -1, FALSE); iface = nm_dhcp_client_get_iface(client); - /* dhcpcd does not allow custom pidfiles; the pidfile is always - * RUNSTATEDIR "dhcpcd-<ifname>.pid". - */ - priv->pid_file = g_strdup_printf(RUNSTATEDIR "/dhcpcd-%s.pid", iface); - dhcpcd_path = nm_dhcp_dhcpcd_get_path(); if (!dhcpcd_path) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "dhcpcd binary not found"); return FALSE; } - /* Kill any existing dhcpcd from the pidfile */ - binary_name = g_path_get_basename(dhcpcd_path); - nm_dhcp_client_stop_existing(priv->pid_file, binary_name); - argv = g_ptr_array_new(); g_ptr_array_add(argv, (gpointer) dhcpcd_path); + /* Don't configure anything, we will do that instead. + * This requires dhcpcd-9.3.3 or newer. + * Older versions only had an option not to install a default route, + * dhcpcd still added addresses and other routes so we no longer support that + * as it doesn't fit how NetworkManager wants to work. + */ + g_ptr_array_add(argv, (gpointer) "--noconfigure"); + g_ptr_array_add(argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */ g_ptr_array_add(argv, (gpointer) "-K"); /* Disable built-in carrier detection */ @@ -113,8 +110,6 @@ ip4_start(NMDhcpClient *client, /* --noarp. Don't request or claim the address by ARP; this also disables IPv4LL. */ g_ptr_array_add(argv, (gpointer) "-A"); - g_ptr_array_add(argv, (gpointer) "-G"); /* Let NM handle routing */ - g_ptr_array_add(argv, (gpointer) "-c"); /* Set script file */ g_ptr_array_add(argv, (gpointer) nm_dhcp_helper_path); @@ -146,8 +141,8 @@ ip4_start(NMDhcpClient *client, if (!g_spawn_async(NULL, (char **) argv->pdata, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL - | G_SPAWN_STDERR_TO_DEV_NULL, + G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL + | G_SPAWN_DO_NOT_REAP_CHILD, nm_utils_setpgid, NULL, &pid, @@ -169,23 +164,32 @@ ip4_start(NMDhcpClient *client, static void stop(NMDhcpClient *client, gboolean release) { - NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(self); - int errsv; - - NM_DHCP_CLIENT_CLASS(nm_dhcp_dhcpcd_parent_class)->stop(client, release); - - if (priv->pid_file) { - if (remove(priv->pid_file) == -1) { - errsv = errno; - _LOGD("could not remove dhcp pid file \"%s\": %d (%s)", - priv->pid_file, - errsv, - nm_strerror_native(errsv)); - } + NMDhcpDhcpcd *self = NM_DHCP_DHCPCD(client); + pid_t pid; + int sig, errsv; + + pid = nm_dhcp_client_get_pid(client); + sig = release ? SIGALRM : SIGTERM; + _LOGD("sending %s to dhcpcd pid %d", sig == SIGALRM ? "SIGALRM" : "SIGTERM", pid); + + /* dhcpcd-9.x features privilege separation. + * It's not our job to track all these processes so we rely on dhcpcd + * to always cleanup after itself. + * Because it also re-parents itself to PID 1, the process cannot be + * reaped or waited for. + * As such, just send the correct signal. + */ + if (kill(pid, sig) == -1) { + errsv = errno; + _LOGE("failed to kill dhcpcd %d:%s", errsv, strerror(errsv)); } - /* FIXME: implement release... */ + /* When this function exits NM expects the PID to be -1. + * This means we also need to stop watching the pid. + * If we need to know the exit status then we need to refactor NM + * to allow a non -1 to mean we're waiting to exit still. + */ + nm_dhcp_client_stop_watch_child(client, pid); } /*****************************************************************************/ @@ -214,8 +218,6 @@ dispose(GObject *object) g_clear_object(&priv->dhcp_listener); } - nm_clear_g_free(&priv->pid_file); - G_OBJECT_CLASS(nm_dhcp_dhcpcd_parent_class)->dispose(object); } diff --git a/src/dhcp/nm-dhcp-helper-api.h b/src/core/dhcp/nm-dhcp-helper-api.h index aa1d203a..ffbf3f72 100644 --- a/src/dhcp/nm-dhcp-helper-api.h +++ b/src/core/dhcp/nm-dhcp-helper-api.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 84fa859d..0f98add1 100644 --- a/src/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "nm-glib-aux/nm-default-glib.h" #include <unistd.h> #include <stdlib.h> diff --git a/src/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index c90590d5..1673bbb7 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-listener.h" diff --git a/src/dhcp/nm-dhcp-listener.h b/src/core/dhcp/nm-dhcp-listener.h index 57d3b0fc..5f3c952c 100644 --- a/src/dhcp/nm-dhcp-listener.h +++ b/src/core/dhcp/nm-dhcp-listener.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c index 665944d7..bc114ad8 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/core/dhcp/nm-dhcp-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-manager.h" diff --git a/src/dhcp/nm-dhcp-manager.h b/src/core/dhcp/nm-dhcp-manager.h index 729d6d4e..f7aba8a0 100644 --- a/src/dhcp/nm-dhcp-manager.h +++ b/src/core/dhcp/nm-dhcp-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c index 7b4e4605..116e1bdb 100644 --- a/src/dhcp/nm-dhcp-nettools.c +++ b/src/core/dhcp/nm-dhcp-nettools.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdlib.h> #include <unistd.h> @@ -13,10 +13,9 @@ #include <ctype.h> #include <net/if_arp.h> -#include "nm-sd-adapt-shared.h" - #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-std-aux/unaligned.h" +#include "nm-glib-aux/nm-str-buf.h" #include "nm-utils.h" #include "nm-config.h" @@ -83,66 +82,39 @@ set_error_nettools(GError **error, int r, const char *message) nm_utils_error_set(error, r, "%s (code %d)", message, r); } -/*****************************************************************************/ - -#define DHCP_MAX_FQDN_LENGTH 255 - -enum { - NM_IN_ADDR_CLASS_A, - NM_IN_ADDR_CLASS_B, - NM_IN_ADDR_CLASS_C, - NM_IN_ADDR_CLASS_INVALID, -}; - -static int -in_addr_class(struct in_addr addr) +static inline int +_client_lease_query(NDhcp4ClientLease *lease, + uint8_t option, + const uint8_t ** datap, + size_t * n_datap) { - switch (ntohl(addr.s_addr) >> 24) { - case 0 ... 127: - return NM_IN_ADDR_CLASS_A; - case 128 ... 191: - return NM_IN_ADDR_CLASS_B; - case 192 ... 223: - return NM_IN_ADDR_CLASS_C; - default: - return NM_IN_ADDR_CLASS_INVALID; - } + return n_dhcp4_client_lease_query(lease, option, (guint8 **) datap, n_datap); } -static gboolean -lease_option_consume(void *out, size_t n_out, uint8_t **datap, size_t *n_datap) -{ - if (*n_datap < n_out) - return FALSE; +/*****************************************************************************/ - memcpy(out, *datap, n_out); - *datap += n_out; - *n_datap -= n_out; - return TRUE; -} +#define DHCP_MAX_FQDN_LENGTH 255 -static gboolean -lease_option_next_in_addr(struct in_addr *addrp, uint8_t **datap, size_t *n_datap) -{ - return lease_option_consume(addrp, sizeof(struct in_addr), datap, n_datap); -} +/*****************************************************************************/ static gboolean -lease_option_next_route(struct in_addr *destp, - uint8_t * plenp, - struct in_addr *gatewayp, - gboolean classless, - uint8_t ** datap, - size_t * n_datap) +lease_option_consume_route(const uint8_t **datap, + size_t * n_datap, + gboolean classless, + in_addr_t * destp, + uint8_t * plenp, + in_addr_t * gatewayp) { - struct in_addr dest = {}, gateway; - uint8_t * data = *datap; + in_addr_t dest; + in_addr_t gateway; + const uint8_t *data = *datap; size_t n_data = *n_datap; uint8_t plen; - uint8_t bytes; if (classless) { - if (!lease_option_consume(&plen, sizeof(plen), &data, &n_data)) + uint8_t bytes; + + if (!nm_dhcp_lease_data_consume(&data, &n_data, &plen, sizeof(plen))) return FALSE; if (plen > 32) @@ -150,30 +122,21 @@ lease_option_next_route(struct in_addr *destp, bytes = plen == 0 ? 0 : ((plen - 1) / 8) + 1; - if (!lease_option_consume(&dest, bytes, &data, &n_data)) + dest = 0; + if (!nm_dhcp_lease_data_consume(&data, &n_data, &dest, bytes)) return FALSE; } else { - if (!lease_option_next_in_addr(&dest, &data, &n_data)) + if (!nm_dhcp_lease_data_consume_in_addr(&data, &n_data, &dest)) return FALSE; - switch (in_addr_class(dest)) { - case NM_IN_ADDR_CLASS_A: - plen = 8; - break; - case NM_IN_ADDR_CLASS_B: - plen = 16; - break; - case NM_IN_ADDR_CLASS_C: - plen = 24; - break; - case NM_IN_ADDR_CLASS_INVALID: + plen = _nm_utils_ip4_get_default_prefix0(dest); + if (plen == 0) return FALSE; - } } - dest.s_addr = nm_utils_ip4_address_clear_host_address(dest.s_addr, plen); + dest = nm_utils_ip4_address_clear_host_address(dest, plen); - if (!lease_option_next_in_addr(&gateway, &data, &n_data)) + if (!nm_dhcp_lease_data_consume_in_addr(&data, &n_data, &gateway)) return FALSE; *destp = dest; @@ -184,170 +147,7 @@ lease_option_next_route(struct in_addr *destp, return TRUE; } -static gboolean -lease_option_print_label(GString *str, size_t n_label, uint8_t **datap, size_t *n_datap) -{ - for (size_t i = 0; i < n_label; ++i) { - uint8_t c; - - if (!lease_option_consume(&c, sizeof(c), datap, n_datap)) - return FALSE; - - switch (c) { - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case '-': - case '_': - g_string_append_c(str, c); - break; - case '.': - case '\\': - g_string_append_printf(str, "\\%c", c); - break; - default: - g_string_append_printf(str, "\\%3d", c); - } - } - - return TRUE; -} - -static gboolean -lease_option_print_domain_name(GString * str, - uint8_t * cache, - size_t * n_cachep, - uint8_t **datap, - size_t * n_datap) -{ - uint8_t * domain; - size_t n_domain, n_cache = *n_cachep; - uint8_t **domainp = datap; - size_t * n_domainp = n_datap; - gboolean first = TRUE; - uint8_t c; - - /* - * We are given two adjacent memory regions. The @cache contains alreday parsed - * domain names, and the @datap contains the remaining data to parse. - * - * A domain name is formed from a sequence of labels. Each label start with - * a length byte, where the two most significant bits are unset. A zero-length - * label indicates the end of the domain name. - * - * Alternatively, a label can be followed by an offset (indicated by the two - * most significant bits being set in the next byte that is read). The offset - * is an offset into the cache, where the next label of the domain name can - * be found. - * - * Note, that each time a jump to an offset is performed, the size of the - * cache shrinks, so this is guaranteed to terminate. - */ - if (cache + n_cache != *datap) - return FALSE; - - for (;;) { - if (!lease_option_consume(&c, sizeof(c), domainp, n_domainp)) - return FALSE; - - switch (c & 0xC0) { - case 0x00: /* label length */ - { - size_t n_label = c; - - if (n_label == 0) { - /* - * We reached the final label of the domain name. Adjust - * the cache to include the consumed data, and return. - */ - *n_cachep = *datap - cache; - return TRUE; - } - - if (!first) - g_string_append_c(str, '.'); - else - first = FALSE; - - if (!lease_option_print_label(str, n_label, domainp, n_domainp)) - return FALSE; - - break; - } - case 0xC0: /* back pointer */ - { - size_t offset = (c & 0x3F) << 16; - - /* - * The offset is given as two bytes (in big endian), where the - * two high bits are masked out. - */ - - if (!lease_option_consume(&c, sizeof(c), domainp, n_domainp)) - return FALSE; - - offset += c; - - if (offset >= n_cache) - return FALSE; - - domain = cache + offset; - n_domain = n_cache - offset; - n_cache = offset; - - domainp = &domain; - n_domainp = &n_domain; - - break; - } - default: - return FALSE; - } - } -} - -static gboolean -lease_get_in_addr(NDhcp4ClientLease *lease, guint8 option, struct in_addr *addrp) -{ - struct in_addr addr; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); - if (r) - return FALSE; - - if (!lease_option_next_in_addr(&addr, &data, &n_data)) - return FALSE; - - if (n_data != 0) - return FALSE; - - *addrp = addr; - return TRUE; -} - -static gboolean -lease_get_u16(NDhcp4ClientLease *lease, uint8_t option, uint16_t *u16p) -{ - uint8_t *data; - size_t n_data; - uint16_t be16; - int r; - - r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); - if (r) - return FALSE; - - if (n_data != sizeof(be16)) - return FALSE; - - memcpy(&be16, data, sizeof(be16)); - - *u16p = ntohs(be16); - return TRUE; -} +/*****************************************************************************/ static gboolean lease_parse_address(NDhcp4ClientLease *lease, @@ -355,15 +155,17 @@ lease_parse_address(NDhcp4ClientLease *lease, GHashTable * options, GError ** error) { - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; struct in_addr a_address; - struct in_addr a_netmask; + in_addr_t a_netmask; struct in_addr a_next_server; guint32 a_plen; guint64 nettools_lifetime; guint32 a_lifetime; guint32 a_timestamp; guint64 a_expiry; + const guint8 * l_data; + gsize l_data_len; + int r; n_dhcp4_client_lease_get_yiaddr(lease, &a_address); if (a_address.s_addr == INADDR_ANY) { @@ -418,44 +220,40 @@ lease_parse_address(NDhcp4ClientLease *lease, / NM_UTILS_NSEC_PER_SEC); } - if (!lease_get_in_addr(lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) { + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &l_data, &l_data_len); + if (r != 0 || !nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &a_netmask)) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "could not get netmask from lease"); return FALSE; } - _nm_utils_inet4_ntop(a_address.s_addr, addr_str); - a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr); + a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, - addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_SUBNET_MASK, - _nm_utils_inet4_ntop(a_netmask.s_addr, addr_str)); + nm_dhcp_option_add_option_in_addr(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, + a_address.s_addr); + nm_dhcp_option_add_option_in_addr(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_SUBNET_MASK, + a_netmask); nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, (guint64) a_lifetime); if (a_expiry != G_MAXUINT64) { - nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - a_expiry); + nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, a_expiry); } n_dhcp4_client_lease_get_siaddr(lease, &a_next_server); if (a_next_server.s_addr != INADDR_ANY) { - _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, - addr_str); + nm_dhcp_option_add_option_in_addr(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, + a_next_server.s_addr); } nm_ip4_config_add_address(ip4_config, @@ -476,46 +274,52 @@ static void lease_parse_address_list(NDhcp4ClientLease * lease, NMIP4Config * ip4_config, NMDhcpOptionDhcp4Options option, - GHashTable * options) + GHashTable * options, + NMStrBuf * sbuf) { - nm_auto_free_gstring GString *str = NULL; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - struct in_addr addr; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); - if (r) + const guint8 *l_data; + gsize l_data_len; + int r; + + r = _client_lease_query(lease, option, &l_data, &l_data_len); + if (r != 0) + return; + + if (l_data_len == 0 || l_data_len % 4 != 0) return; - nm_gstring_prepare(&str); + nm_str_buf_reset(sbuf); - while (lease_option_next_in_addr(&addr, &data, &n_data)) { - _nm_utils_inet4_ntop(addr.s_addr, addr_str); - g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + for (; l_data_len > 0; l_data_len -= 4, l_data += 4) { + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + const in_addr_t addr = unaligned_read_ne32(l_data); + + nm_str_buf_append_required_delimiter(sbuf, ' '); + nm_str_buf_append(sbuf, _nm_utils_inet4_ntop(addr, addr_str)); switch (option) { case NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER: - if (addr.s_addr == 0 || nm_ip4_addr_is_localhost(addr.s_addr)) { + if (addr == 0 || nm_ip4_addr_is_localhost(addr)) { /* Skip localhost addresses, like also networkd does. * See https://github.com/systemd/systemd/issues/4524. */ continue; } - nm_ip4_config_add_nameserver(ip4_config, addr.s_addr); + nm_ip4_config_add_nameserver(ip4_config, addr); break; case NM_DHCP_OPTION_DHCP4_NIS_SERVERS: - nm_ip4_config_add_nis_server(ip4_config, addr.s_addr); + nm_ip4_config_add_nis_server(ip4_config, addr); break; case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER: - nm_ip4_config_add_wins(ip4_config, addr.s_addr); + nm_ip4_config_add_wins(ip4_config, addr); + break; + case NM_DHCP_OPTION_DHCP4_NTP_SERVER: break; default: nm_assert_not_reached(); } } - nm_dhcp_option_add_option(options, _nm_dhcp_option_dhcp4_options, option, str->str); + nm_dhcp_option_add_option(options, AF_INET, option, nm_str_buf_get_str(sbuf)); } static void @@ -523,39 +327,37 @@ lease_parse_routes(NDhcp4ClientLease *lease, NMIP4Config * ip4_config, GHashTable * options, guint32 route_table, - guint32 route_metric) + guint32 route_metric, + NMStrBuf * sbuf) { - nm_auto_free_gstring GString *str = NULL; - char dest_str[NM_UTILS_INET_ADDRSTRLEN]; - char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; - const char * s; - struct in_addr dest, gateway; - uint8_t plen; - guint32 m; - gboolean has_router_from_classless = FALSE, has_classless = FALSE; - guint32 default_route_metric = route_metric; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - &data, - &n_data); - if (!r) { - nm_gstring_prepare(&str); + char dest_str[NM_UTILS_INET_ADDRSTRLEN]; + char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; + in_addr_t dest; + 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; + const guint8 *l_data; + gsize l_data_len; + int r; + + r = _client_lease_query(lease, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, + &l_data, + &l_data_len); + if (r == 0) { + nm_str_buf_reset(sbuf); has_classless = TRUE; - while (lease_option_next_route(&dest, &plen, &gateway, TRUE, &data, &n_data)) { - _nm_utils_inet4_ntop(dest.s_addr, dest_str); - _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); + while (lease_option_consume_route(&l_data, &l_data_len, TRUE, &dest, &plen, &gateway)) { + _nm_utils_inet4_ntop(dest, dest_str); + _nm_utils_inet4_ntop(gateway, gateway_str); - g_string_append_printf(nm_gstring_add_space_delimiter(str), - "%s/%d %s", - dest_str, - (int) plen, - gateway_str); + nm_str_buf_append_required_delimiter(sbuf, ' '); + nm_str_buf_append_printf(sbuf, "%s/%d %s", dest_str, (int) plen, gateway_str); if (plen == 0) { /* if there are multiple default routes, we add them with differing @@ -572,34 +374,32 @@ lease_parse_routes(NDhcp4ClientLease *lease, nm_ip4_config_add_route( ip4_config, &((const NMPlatformIP4Route){ - .network = dest.s_addr, + .network = dest, .plen = plen, - .gateway = gateway.s_addr, + .gateway = gateway, .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .metric = m, .table_coerced = nm_platform_route_table_coerce(route_table), }), NULL); } + nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - str->str); + nm_str_buf_get_str(sbuf)); } - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, &data, &n_data); - if (!r) { - nm_gstring_prepare(&str); + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, &l_data, &l_data_len); + if (r == 0) { + nm_str_buf_reset(sbuf); - while (lease_option_next_route(&dest, &plen, &gateway, FALSE, &data, &n_data)) { - _nm_utils_inet4_ntop(dest.s_addr, dest_str); - _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); + while (lease_option_consume_route(&l_data, &l_data_len, FALSE, &dest, &plen, &gateway)) { + _nm_utils_inet4_ntop(dest, dest_str); + _nm_utils_inet4_ntop(gateway, gateway_str); - g_string_append_printf(nm_gstring_add_space_delimiter(str), - "%s/%d %s", - dest_str, - (int) plen, - gateway_str); + nm_str_buf_append_required_delimiter(sbuf, ' '); + nm_str_buf_append_printf(sbuf, "%s/%d %s", dest_str, (int) plen, gateway_str); if (has_classless) { /* RFC 3443: if the DHCP server returns both a Classless Static Routes @@ -619,30 +419,31 @@ lease_parse_routes(NDhcp4ClientLease *lease, nm_ip4_config_add_route( ip4_config, &((const NMPlatformIP4Route){ - .network = dest.s_addr, + .network = dest, .plen = plen, - .gateway = gateway.s_addr, + .gateway = gateway, .rt_source = NM_IP_CONFIG_SOURCE_DHCP, .metric = route_metric, .table_coerced = nm_platform_route_table_coerce(route_table), }), NULL); } + nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, - str->str); + nm_str_buf_get_str(sbuf)); } - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROUTER, &data, &n_data); - if (!r) { - nm_gstring_prepare(&str); + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROUTER, &l_data, &l_data_len); + if (r == 0) { + nm_str_buf_reset(sbuf); - while (lease_option_next_in_addr(&gateway, &data, &n_data)) { - s = _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); - g_string_append(nm_gstring_add_space_delimiter(str), s); + while (nm_dhcp_lease_data_consume_in_addr(&l_data, &l_data_len, &gateway)) { + nm_str_buf_append_required_delimiter(sbuf, ' '); + nm_str_buf_append(sbuf, _nm_utils_inet4_ntop(gateway, gateway_str)); - if (gateway.s_addr == 0) { + if (gateway == 0) { /* silently skip 0.0.0.0 */ continue; } @@ -667,262 +468,45 @@ lease_parse_routes(NDhcp4ClientLease *lease, ip4_config, &((const NMPlatformIP4Route){ .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .gateway = gateway.s_addr, + .gateway = gateway, .table_coerced = nm_platform_route_table_coerce(route_table), .metric = m, }), NULL); } + nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, - str->str); - } -} - -static void -lease_parse_mtu(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) -{ - uint16_t mtu; - - if (!lease_get_u16(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &mtu)) - return; - - if (mtu < 68) - return; - - nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, - mtu); - nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); -} - -static void -lease_parse_metered(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) -{ - gboolean metered = FALSE; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &data, &n_data); - if (r) - metered = FALSE; - else - metered = !!memmem(data, n_data, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")); - - /* TODO: expose the vendor specific option when present */ - nm_ip4_config_set_metered(ip4_config, metered); -} - -static void -lease_parse_ntps(NDhcp4ClientLease *lease, GHashTable *options) -{ - nm_auto_free_gstring GString *str = NULL; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - struct in_addr addr; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NTP_SERVER, &data, &n_data); - if (r) - return; - - nm_gstring_prepare(&str); - - while (lease_option_next_in_addr(&addr, &data, &n_data)) { - _nm_utils_inet4_ntop(addr.s_addr, addr_str); - g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + nm_str_buf_get_str(sbuf)); } - - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NTP_SERVER, - str->str); -} - -static void -lease_parse_hostname(NDhcp4ClientLease *lease, GHashTable *options) -{ - nm_auto_free_gstring GString *str = NULL; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &data, &n_data); - if (r) - return; - - str = g_string_new_len((char *) data, n_data); - - if (nm_utils_is_localhost(str->str)) - return; - - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_HOST_NAME, - str->str); -} - -static void -lease_parse_domainname(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) -{ - nm_auto_free_gstring GString *str = NULL; - gs_strfreev char ** domains = NULL; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &data, &n_data); - if (r) - return; - - str = g_string_new_len((char *) data, n_data); - - /* Multiple domains sometimes stuffed into option 15 "Domain Name". */ - domains = g_strsplit(str->str, " ", 0); - nm_gstring_prepare(&str); - - for (char **d = domains; *d; d++) { - if (nm_utils_is_localhost(*d)) - return; - - g_string_append(nm_gstring_add_space_delimiter(str), *d); - nm_ip4_config_add_domain(ip4_config, *d); - } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, - str->str); -} - -char ** -nm_dhcp_parse_search_list(guint8 *data, size_t n_data) -{ - GPtrArray *array = NULL; - guint8 * cache = data; - size_t n_cache = 0; - - for (;;) { - nm_auto_free_gstring GString *domain = NULL; - - nm_gstring_prepare(&domain); - - if (!lease_option_print_domain_name(domain, cache, &n_cache, &data, &n_data)) - break; - - if (!array) - array = g_ptr_array_new(); - - g_ptr_array_add(array, g_string_free(domain, FALSE)); - domain = NULL; - } - - if (array) { - g_ptr_array_add(array, NULL); - return (char **) g_ptr_array_free(array, FALSE); - } else - return NULL; } static void lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - uint8_t * data; - size_t n_data; - gs_strfreev char ** domains = NULL; - guint i; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, &data, &n_data); - if (r) - return; - - domains = nm_dhcp_parse_search_list(data, n_data); - nm_gstring_prepare(&str); - - for (i = 0; domains && domains[i]; i++) { - g_string_append(nm_gstring_add_space_delimiter(str), domains[i]); - nm_ip4_config_add_search(ip4_config, domains[i]); - } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, - str->str); -} - -static void -lease_parse_root_path(NDhcp4ClientLease *lease, GHashTable *options) -{ - nm_auto_free_gstring GString *str = NULL; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &data, &n_data); - if (r) + gs_strfreev char **domains = NULL; + const guint8 * l_data; + gsize l_data_len; + guint i; + int r; + + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, &l_data, &l_data_len); + if (r != 0) return; - str = g_string_new_len((char *) data, n_data); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROOT_PATH, - str->str); -} - -static void -lease_parse_wpad(NDhcp4ClientLease *lease, GHashTable *options) -{ - gs_free char *wpad = NULL; - uint8_t * data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query(lease, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - &data, - &n_data); - if (r) - return; - - nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &wpad); - if (wpad == NULL) - wpad = g_strndup((char *) data, n_data); - - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - wpad); -} - -static void -lease_parse_nis_domain(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) -{ - gs_free char *str_free = NULL; - const char * str; - uint8_t * data; - size_t n_data; - guint i; - int r; + domains = nm_dhcp_lease_data_parse_search_list(l_data, l_data_len); - r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &data, &n_data); - if (r) + if (!domains || !domains[0]) return; - for (i = 0; i < n_data; i++) { - if (!nm_is_ascii((char) data[i])) - return; - } + for (i = 0; domains[i]; i++) + nm_ip4_config_add_search(ip4_config, domains[i]); - str = nm_strndup_a(300, (const char *) data, n_data, &str_free); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, - str); - nm_ip4_config_set_nis_domain(ip4_config, str); + nm_dhcp_option_take_option(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, + g_strjoinv(" ", domains)); } static void @@ -932,8 +516,8 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options) for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) { gs_free char *option_string = NULL; - guint8 * data; - gsize n_data; + const guint8 *l_data; + gsize l_data_len; int r; /* We manage private options 249 (private classless static route) and 252 (wpad) in a special @@ -943,15 +527,12 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options) NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) continue; - r = n_dhcp4_client_lease_query(lease, i, &data, &n_data); + r = _client_lease_query(lease, i, &l_data, &l_data_len); if (r) continue; - option_string = nm_utils_bin2hexstr_full(data, n_data, ':', FALSE, NULL); - nm_dhcp_option_take_option(options, - _nm_dhcp_option_dhcp4_options, - i, - g_steal_pointer(&option_string)); + option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL); + nm_dhcp_option_take_option(options, AF_INET, i, g_steal_pointer(&option_string)); } } @@ -965,8 +546,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, 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; + 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); @@ -976,20 +566,145 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, if (!lease_parse_address(lease, ip4_config, options, error)) return NULL; - lease_parse_routes(lease, ip4_config, options, route_table, route_metric); - lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options); - lease_parse_domainname(lease, ip4_config, options); + r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s); + if (r == 0) { + nm_dhcp_option_add_option_in_addr(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_SERVER_ID, + v_inaddr_s.s_addr); + } + + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_BROADCAST, &l_data, &l_data_len); + if (r == 0 && nm_dhcp_lease_data_parse_in_addr(l_data, l_data_len, &v_inaddr)) { + nm_dhcp_option_add_option_in_addr(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_BROADCAST, + v_inaddr); + } + + lease_parse_routes(lease, ip4_config, options, route_table, route_metric, &sbuf); + + lease_parse_address_list(lease, + ip4_config, + 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)) { + gs_free const char **domains = NULL; + + nm_str_buf_reset(&sbuf); + nm_str_buf_append_len0(&sbuf, (const char *) l_data, l_data_len); + + /* Multiple domains sometimes stuffed into option 15 "Domain Name". */ + domains = nm_utils_strsplit_set(nm_str_buf_get_str(&sbuf), " "); + + nm_str_buf_reset(&sbuf); + if (domains) { + gsize i; + + for (i = 0; domains[i]; i++) { + gs_free char *s = NULL; + + s = nm_dhcp_lease_data_parse_domain_validate(domains[i]); + if (!s) + continue; + + nm_str_buf_append_required_delimiter(&sbuf, ' '); + nm_str_buf_append(&sbuf, s); + nm_ip4_config_add_domain(ip4_config, s); + } + } + + if (sbuf.len > 0) { + nm_dhcp_option_add_option(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + nm_str_buf_get_str(&sbuf)); + } + } + lease_parse_search_domains(lease, ip4_config, options); - lease_parse_mtu(lease, ip4_config, options); - lease_parse_metered(lease, ip4_config, options); - - lease_parse_hostname(lease, options); - lease_parse_ntps(lease, options); - lease_parse_root_path(lease, options); - lease_parse_wpad(lease, options); - lease_parse_nis_domain(lease, ip4_config, options); - lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options); - lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, 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); + } + + 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); + + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &l_data, &l_data_len); + if (r == 0) { + gs_free char *s = NULL; + + if (nm_dhcp_lease_data_parse_domain(l_data, l_data_len, &s)) { + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s); + } + } + + lease_parse_address_list(lease, ip4_config, 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)) { + /* https://tools.ietf.org/html/rfc2132#section-3.19 + * + * The path is formatted as a character string consisting of + * characters from the NVT ASCII character set. + * + * We still accept any character set and backslash escape it! */ + if (l_data_len == 0) { + /* "Its minimum length is 1." */ + } else { + nm_dhcp_option_add_option_utf8safe_escape(options, + AF_INET, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + l_data, + l_data_len); + } + } + + r = _client_lease_query(lease, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, + &l_data, + &l_data_len); + if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) { + /* https://tools.ietf.org/html/draft-ietf-wrec-wpad-01#section-4.4.1 + * + * 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); + } + + r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len); + if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) { + gs_free char *to_free = NULL; + + /* https://tools.ietf.org/html/rfc2132#section-8.1 */ + + v_str = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free); + + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str); + nm_ip4_config_set_nis_domain(ip4_config, v_str); + } + + lease_parse_address_list(lease, ip4_config, 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_private_options(lease, options); NM_SET_OUT(out_options, g_steal_pointer(&options)); @@ -1001,25 +716,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, static void lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_file) { - struct in_addr a_address; - nm_auto_free_gstring GString *new_contents = NULL; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + struct in_addr a_address; + nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; gs_free_error GError *error = NULL; nm_assert(lease); nm_assert(lease_file); - new_contents = g_string_new("# This is private data. Do not parse.\n"); - n_dhcp4_client_lease_get_yiaddr(lease, &a_address); if (a_address.s_addr == INADDR_ANY) return; - g_string_append_printf(new_contents, - "ADDRESS=%s\n", - _nm_utils_inet4_ntop(a_address.s_addr, sbuf)); + nm_str_buf_append(&sbuf, "# This is private data. Do not parse.\n"); + nm_str_buf_append_printf(&sbuf, + "ADDRESS=%s\n", + _nm_utils_inet4_ntop(a_address.s_addr, addr_str)); - if (!g_file_set_contents(lease_file, new_contents->str, -1, &error)) + if (!g_file_set_contents(lease_file, nm_str_buf_get_str_unsafe(&sbuf), sbuf.len, &error)) _LOGW("error saving lease to %s: %s", lease_file, error->message); } @@ -1049,7 +763,7 @@ bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended) return; } - nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); + 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), @@ -1127,9 +841,9 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event) } static gboolean -dhcp4_event_cb(int fd, GIOCondition condition, gpointer data) +dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data) { - NMDhcpNettools * self = data; + NMDhcpNettools * self = user_data; NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); NDhcp4ClientEvent * event; int r; @@ -1375,7 +1089,7 @@ ip4_start(NMDhcpClient *client, } /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) { if (_nm_dhcp_option_dhcp4_options[i].include) { nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); n_dhcp4_client_probe_config_request_option(config, diff --git a/src/dhcp/nm-dhcp-options.c b/src/core/dhcp/nm-dhcp-options.c index 58d38201..3537cd14 100644 --- a/src/dhcp/nm-dhcp-options.c +++ b/src/core/dhcp/nm-dhcp-options.c @@ -1,17 +1,19 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-options.h" -#define REQPREFIX "requested_" +#include "nm-glib-aux/nm-str-buf.h" -#define REQ(_num, _name, _include) \ - { \ - .name = REQPREFIX ""_name, .option_num = _num, .include = _include, \ +/*****************************************************************************/ + +#define REQ(_num, _name, _include) \ + { \ + .name = NM_DHCP_OPTION_REQPREFIX ""_name, .option_num = _num, .include = _include, \ } const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { @@ -167,8 +169,24 @@ const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { REQ(NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE), REQ(NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE), +}; - {0}}; +static const NMDhcpOption *const _sorted_options_4[G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options)] = { +#define A(idx) (&_nm_dhcp_option_dhcp4_options[(idx)]) + A(0), A(1), A(8), A(18), A(19), A(2), A(20), A(21), A(22), A(23), A(24), A(3), + A(25), A(26), A(4), A(27), A(17), A(28), A(29), A(30), A(31), A(32), A(33), A(34), + A(35), A(5), A(36), A(6), A(37), A(38), A(39), A(40), A(9), A(41), A(42), A(43), + A(44), A(45), A(46), A(10), A(11), A(12), A(47), A(48), A(49), A(50), A(51), A(52), + A(13), A(53), A(54), A(55), A(57), A(58), A(59), A(60), A(61), A(62), A(63), A(64), + A(65), A(66), A(67), A(68), A(69), A(70), A(71), A(72), A(73), A(74), A(75), A(76), + A(77), A(78), A(79), A(80), A(81), A(82), A(83), A(84), A(85), A(86), A(87), A(56), + A(88), A(89), A(90), A(91), A(92), A(93), A(14), A(7), A(94), A(95), A(96), A(97), + A(98), A(99), A(100), A(101), A(102), A(103), A(104), A(105), A(106), A(107), A(108), A(109), + A(110), A(111), A(112), A(113), A(114), A(115), A(116), A(117), A(118), A(119), A(120), A(121), + A(122), A(123), A(124), A(125), A(126), A(127), A(128), A(129), A(130), A(131), A(132), A(133), + A(134), A(15), A(135), A(136), A(16), A(137), A(138), A(139), A(140), A(141), +#undef A +}; const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = { REQ(NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE), @@ -194,73 +212,235 @@ const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = { REQ(NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE), REQ(NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE), REQ(NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE), +}; + +#undef REQ + +static const NMDhcpOption *const _sorted_options_6[G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options)] = { +#define A(idx) (&_nm_dhcp_option_dhcp6_options[(idx)]) + A(0), + A(1), + A(2), + A(3), + A(4), + A(5), + A(6), + A(7), + A(8), + A(9), + A(10), + A(11), + A(12), + A(13), + A(14), + A(15), +#undef A +}; + +/*****************************************************************************/ + +static int +_sorted_options_generate_sort(gconstpointer pa, gconstpointer pb, gpointer user_data) +{ + const NMDhcpOption *const *a = pa; + const NMDhcpOption *const *b = pb; + + NM_CMP_DIRECT((*a)->option_num, (*b)->option_num); + return nm_assert_unreachable_val(0); +} + +static char * +_sorted_options_generate(const NMDhcpOption *base, const NMDhcpOption *const *sorted, guint n) +{ + gs_free const NMDhcpOption **sort2 = NULL; + NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE); + guint i; + + sort2 = nm_memdup(sorted, n * sizeof(sorted[0])); + + g_qsort_with_data(sort2, n, sizeof(sort2[0]), _sorted_options_generate_sort, NULL); + + for (i = 0; i < n; i++) { + if (i > 0) + nm_str_buf_append(&sbuf, ", "); + nm_str_buf_append_printf(&sbuf, "A(%d)", (int) (sort2[i] - base)); + } + + return nm_str_buf_finalize(&sbuf, NULL); +} + +_nm_unused static void +_ASSERT_sorted(int IS_IPv4, const NMDhcpOption *const *const sorted, int n) + +{ + const NMDhcpOption *const options = + IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options; + int i; + int j; + gs_free char *sorted_msg = NULL; + + for (i = 0; i < n; i++) { + const NMDhcpOption *opt = sorted[i]; + + g_assert(opt); + g_assert(opt >= options); + g_assert(opt < &options[n]); + + for (j = 0; j < i; j++) { + const NMDhcpOption *opt2 = sorted[j]; + + if (opt == opt2) { + g_error("%s:%d: the _sorted_options_%c at [%d] (opt=%u, %s) is duplicated at " + "[%d] (SORT: %s)", + __FILE__, + __LINE__, + IS_IPv4 ? '4' : '6', + i, + opt->option_num, + opt->name, + j, + (sorted_msg = _sorted_options_generate(options, sorted, n))); + } + } - {0}}; + if (i > 0) { + const NMDhcpOption *opt2 = sorted[i - 1]; -const char * -nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option) + if (opt2->option_num >= opt->option_num) { + g_error("%s:%d: the _sorted_options_%c at [%d] (opt=%u, %s) should come before " + "[%d] (opt=%u, %s) (SORT: %s)", + __FILE__, + __LINE__, + IS_IPv4 ? '4' : '6', + i, + opt->option_num, + opt->name, + i - 1, + opt2->option_num, + opt2->name, + (sorted_msg = _sorted_options_generate(options, sorted, n))); + } + } + } +} + +/*****************************************************************************/ + +const NMDhcpOption * +nm_dhcp_option_find(int addr_family, guint option) { - guint i = 0; + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMDhcpOption *const *const sorted = IS_IPv4 ? _sorted_options_4 : _sorted_options_6; + const int n = IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options) + : G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options); + int imin = 0; + int imax = n - 1; + int imid = (n - 1) / 2; + +#if NM_MORE_ASSERTS > 10 + nm_assert(n < G_MAXINT / 2); + if (IS_IPv4 && !NM_MORE_ASSERT_ONCE(10)) { + /* already checked */ + } else if (!IS_IPv4 && !NM_MORE_ASSERT_ONCE(10)) { + /* already checked */ + } else + _ASSERT_sorted(IS_IPv4, sorted, n); +#endif + + for (;;) { + const guint o = sorted[imid]->option_num; - while (requests[i].name) { - if (requests[i].option_num == option) - return requests[i].name + NM_STRLEN(REQPREFIX); - i++; + if (G_UNLIKELY(o == option)) + return sorted[imid]; + + if (o < option) + imin = imid + 1; + else + imax = imid - 1; + + if (G_UNLIKELY(imin > imax)) + break; + + imid = (imin + imax) / 2; } /* Option should always be found */ - nm_assert_not_reached(); - return NULL; + return nm_assert_unreachable_val(NULL); } +/*****************************************************************************/ + void -nm_dhcp_option_take_option(GHashTable * options, - const NMDhcpOption *requests, - guint option, - char * value) +nm_dhcp_option_take_option(GHashTable *options, int addr_family, guint option, char *value) { - nm_assert(options); - nm_assert(requests); + nm_assert_addr_family(addr_family); nm_assert(value); nm_assert(g_utf8_validate(value, -1, NULL)); - g_hash_table_insert(options, (gpointer) nm_dhcp_option_request_string(requests, option), value); + if (!options) { + nm_assert_not_reached(); + g_free(value); + return; + } + + g_hash_table_insert(options, + (gpointer) nm_dhcp_option_request_string(addr_family, option), + value); } void -nm_dhcp_option_add_option(GHashTable * options, - const NMDhcpOption *requests, - guint option, - const char * value) +nm_dhcp_option_add_option(GHashTable *options, int addr_family, guint option, const char *value) { - if (options) - nm_dhcp_option_take_option(options, requests, option, g_strdup(value)); + nm_dhcp_option_take_option(options, addr_family, option, g_strdup(value)); } void -nm_dhcp_option_add_option_u64(GHashTable * options, - const NMDhcpOption *requests, - guint option, - guint64 value) +nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options, + int addr_family, + guint option, + const guint8 *data, + gsize n_data) { - if (options) - nm_dhcp_option_take_option(options, - requests, - option, - g_strdup_printf("%" G_GUINT64_FORMAT, value)); + gs_free char *to_free = NULL; + const char * escaped; + + escaped = nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &to_free); + nm_dhcp_option_add_option(options, addr_family, option, escaped ?: ""); } void -nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests) +nm_dhcp_option_add_option_u64(GHashTable *options, int addr_family, guint option, guint64 value) { - guint i; + nm_dhcp_option_take_option(options, + addr_family, + option, + g_strdup_printf("%" G_GUINT64_FORMAT, value)); +} - if (!options) - return; +void +nm_dhcp_option_add_option_in_addr(GHashTable *options, + int addr_family, + guint option, + in_addr_t value) +{ + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + nm_dhcp_option_add_option(options, addr_family, option, _nm_utils_inet4_ntop(value, sbuf)); +} + +void +nm_dhcp_option_add_requests_to_options(GHashTable *options, int addr_family) +{ + const int IS_IPv4 = NM_IS_IPv4(addr_family); + const NMDhcpOption *const all_options = + IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options; + int n_options = IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options) + : G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options); + int i; - for (i = 0; requests[i].name; i++) { - if (requests[i].include) - g_hash_table_insert(options, (gpointer) requests[i].name, g_strdup("1")); + for (i = 0; i < n_options; i++) { + if (all_options[i].include) + g_hash_table_insert(options, (gpointer) all_options[i].name, g_strdup("1")); } } diff --git a/src/dhcp/nm-dhcp-options.h b/src/core/dhcp/nm-dhcp-options.h index 6c867c40..585f1187 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/core/dhcp/nm-dhcp-options.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ @@ -177,29 +177,50 @@ typedef enum { } NMDhcpOptionDhcp6Options; +#define NM_DHCP_OPTION_REQPREFIX "requested_" + typedef struct { const char *name; uint16_t option_num; bool include; } NMDhcpOption; -extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[]; -extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[]; +extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[142]; +extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[16]; + +static inline const char * +nm_dhcp_option_get_name(const NMDhcpOption *option) +{ + nm_assert(option); + nm_assert(option->name); + nm_assert(NM_STR_HAS_PREFIX(option->name, NM_DHCP_OPTION_REQPREFIX)); + + return &option->name[NM_STRLEN(NM_DHCP_OPTION_REQPREFIX)]; +} + +const NMDhcpOption *nm_dhcp_option_find(int addr_family, guint option); + +static inline const char * +nm_dhcp_option_request_string(int addr_family, guint option) +{ + return nm_dhcp_option_get_name(nm_dhcp_option_find(addr_family, option)); +} -const char *nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option); -void nm_dhcp_option_take_option(GHashTable * options, - const NMDhcpOption *requests, - guint option, - char * value); -void nm_dhcp_option_add_option(GHashTable * options, - const NMDhcpOption *requests, - guint option, - const char * value); -void nm_dhcp_option_add_option_u64(GHashTable * options, - const NMDhcpOption *requests, - guint option, - guint64 value); -void nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests); +void nm_dhcp_option_take_option(GHashTable *options, int addr_family, guint option, char *value); +void +nm_dhcp_option_add_option(GHashTable *options, int addr_family, guint option, const char *value); +void nm_dhcp_option_add_option_utf8safe_escape(GHashTable * options, + int addr_family, + guint option, + const guint8 *data, + gsize n_data); +void nm_dhcp_option_add_option_in_addr(GHashTable *options, + int addr_family, + guint option, + in_addr_t value); +void +nm_dhcp_option_add_option_u64(GHashTable *options, int addr_family, guint option, guint64 value); +void nm_dhcp_option_add_requests_to_options(GHashTable *options, int addr_family); GHashTable *nm_dhcp_option_create_options_dict(void); #endif /* __NM_DHCP_OPTIONS_H__ */ diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index f9297223..b92a9073 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdlib.h> #include <unistd.h> @@ -138,32 +138,26 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, options = out_options ? nm_dhcp_option_create_options_dict() : NULL; _nm_utils_inet4_ntop(a_address.s_addr, addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, - addr_str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str); a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr); nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, _nm_utils_inet4_ntop(a_netmask.s_addr, addr_str)); nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, a_lifetime); nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_NM_EXPIRY, (guint64)(ts_time + a_lifetime)); if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) { _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, - addr_str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str); } nm_ip4_config_add_address(ip4_config, @@ -179,18 +173,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) { _nm_utils_inet4_ntop(server_id.s_addr, addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_SERVER_ID, - addr_str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_SERVER_ID, addr_str); } if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) { _nm_utils_inet4_ntop(broadcast.s_addr, addr_str); - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_BROADCAST, - addr_str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_BROADCAST, addr_str); } num = sd_dhcp_lease_get_dns(lease, &addr_list); @@ -208,7 +196,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr); } nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, str->str); } @@ -221,7 +209,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_ip4_config_add_search(ip4_config, search_domains[i]); } nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, str->str); } @@ -230,10 +218,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, gs_strfreev char **domains = NULL; char ** d; - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, - s); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s); /* Multiple domains sometimes stuffed into option 15 "Domain Name". * As systemd escapes such characters, split them at \\032. */ @@ -243,10 +228,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, } if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) { - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_HOST_NAME, - s); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s); } num = sd_dhcp_lease_get_routes(lease, &routes); @@ -348,12 +330,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, if (str_classless && str_classless->len > 0) nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, str_classless->str); if (str_static && str_static->len > 0) nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, str_static->str); } @@ -400,17 +382,11 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, }), NULL); } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROUTER, - str->str); + 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, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, - 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); } @@ -421,38 +397,29 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, _nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str); } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NTP_SERVER, - str->str); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str); } if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) { - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROOT_PATH, - s); + nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s); } if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) { nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, renewal); } if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) { nm_dhcp_option_add_option_u64(options, - _nm_dhcp_option_dhcp4_options, + AF_INET, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, rebinding); } if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) { - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, - s); + 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) @@ -473,10 +440,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, g_free(option_string); continue; } - nm_dhcp_option_take_option(options, - _nm_dhcp_option_dhcp4_options, - private_options[i].code, - option_string); + nm_dhcp_option_take_option(options, AF_INET, private_options[i].code, option_string); } } NM_SET_OUT(out_options, g_steal_pointer(&options)); @@ -518,7 +482,7 @@ bound4_handle(NMDhcpSystemd *self, gboolean extended) return; } - nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); + 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), @@ -568,6 +532,8 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) return -ENOMSG; } break; + case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE: + break; default: _LOGW("unhandled DHCP event %d", event); break; @@ -599,6 +565,9 @@ ip4_start(NMDhcpClient *client, const char * hostname; const char * mud_url; int r, i; + GBytes * bcast_hwaddr; + const uint8_t * bcast_hwaddr_arr; + gsize bcast_hwaddr_len; g_return_val_if_fail(!priv->client4, FALSE); g_return_val_if_fail(!priv->client6, FALSE); @@ -623,7 +592,19 @@ ip4_start(NMDhcpClient *client, nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address"); return FALSE; } - r = sd_dhcp_client_set_mac(sd_client, hwaddr_arr, hwaddr_len, (guint16) arp_type); + + bcast_hwaddr_arr = NULL; + if ((bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self)))) { + bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len); + if (bcast_hwaddr_len != hwaddr_len) + bcast_hwaddr_arr = NULL; + } + + r = sd_dhcp_client_set_mac(sd_client, + hwaddr_arr, + bcast_hwaddr_arr, + hwaddr_len, + (guint16) arp_type); if (r < 0) { nm_utils_error_set_errno(error, r, "failed to set MAC address: %s"); return FALSE; @@ -685,7 +666,7 @@ ip4_start(NMDhcpClient *client, } /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) { if (_nm_dhcp_option_dhcp4_options[i].include) { nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); r = sd_dhcp_client_set_request_option(sd_client, @@ -804,10 +785,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, g_string_append(nm_gstring_add_space_delimiter(str), addr_str); }; if (str->len) - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, - str->str); + 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) { g_set_error_literal(error, @@ -825,10 +803,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, g_string_append(nm_gstring_add_space_delimiter(str), addr_str); nm_ip6_config_add_nameserver(ip6_config, &dns[i]); } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_DNS_SERVERS, - str->str); + nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str); } num = sd_dhcp6_lease_get_domains(lease, &domains); @@ -838,17 +813,11 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, g_string_append(nm_gstring_add_space_delimiter(str), domains[i]); nm_ip6_config_add_search(ip6_config, domains[i]); } - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, - str->str); + nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str); } if (sd_dhcp6_lease_get_fqdn(lease, &s) >= 0) { - nm_dhcp_option_add_option(options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_FQDN, - s); + nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s); } NM_SET_OUT(out_options, g_steal_pointer(&options)); @@ -969,8 +938,11 @@ ip6_start(NMDhcpClient * client, _LOGT("dhcp-client6: set %p", sd_client); - if (nm_dhcp_client_get_info_only(client)) - sd_dhcp6_client_set_information_request(sd_client, 1); + if (nm_dhcp_client_get_info_only(client)) { + sd_dhcp6_client_set_address_request(sd_client, 0); + if (needed_prefixes == 0) + sd_dhcp6_client_set_information_request(sd_client, 1); + } r = sd_dhcp6_client_set_iaid(sd_client, nm_dhcp_client_get_iaid(client)); if (r < 0) { @@ -1000,7 +972,7 @@ ip6_start(NMDhcpClient * client, } /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp6_options[i].name; i++) { + for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options); i++) { if (_nm_dhcp_option_dhcp6_options[i].include) { r = sd_dhcp6_client_set_request_option(sd_client, _nm_dhcp_option_dhcp6_options[i].option_num); diff --git a/src/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c index bf10e2b5..646411e2 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/core/dhcp/nm-dhcp-utils.c @@ -1,14 +1,17 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <unistd.h> #include <arpa/inet.h> +#include "nm-std-aux/unaligned.h" #include "nm-glib-aux/nm-dedup-multi.h" +#include "nm-glib-aux/nm-str-buf.h" +#include "systemd/nm-sd-utils-shared.h" #include "nm-dhcp-utils.h" #include "nm-utils.h" @@ -834,3 +837,285 @@ nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease) return g_strdup_printf("%s|%s", iaid, start); } + +/*****************************************************************************/ + +gboolean +nm_dhcp_lease_data_parse_u16(const guint8 *data, gsize n_data, uint16_t *out_val) +{ + if (n_data != 2) + return FALSE; + + *out_val = unaligned_read_be16(data); + return TRUE; +} + +gboolean +nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, uint16_t *out_val) +{ + uint16_t mtu; + + if (!nm_dhcp_lease_data_parse_u16(data, n_data, &mtu)) + return FALSE; + + if (mtu < 68) { + /* https://tools.ietf.org/html/rfc2132#section-5.1: + * + * The minimum legal value for the MTU is 68. */ + return FALSE; + } + + *out_val = mtu; + return TRUE; +} + +gboolean +nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_len) +{ + /* WARNING: this function only validates that the string does not contain + * NUL characters (and ignores trailing NULs). It does not check character + * encoding! */ + + while (n_data > 0 && data[n_data - 1] == '\0') + n_data--; + + if (n_data > 0) { + if (memchr(data, n_data, '\0')) { + /* we accept trailing NUL, but none in between. + * + * https://tools.ietf.org/html/rfc2132#section-2 + * https://github.com/systemd/systemd/issues/1337 */ + return FALSE; + } + } + + NM_SET_OUT(out_new_len, n_data); + return TRUE; +} + +char * +nm_dhcp_lease_data_parse_domain_validate(const char *str) +{ + gs_free char *s = NULL; + + s = nm_sd_dns_name_normalize(str); + if (!s) + return NULL; + + if (nm_str_is_empty(s) || (s[0] == '.' && s[1] == '\0')) { + /* root domains are not allowed. */ + return NULL; + } + + if (nm_utils_is_localhost(s)) + return NULL; + + if (!g_utf8_validate(s, -1, NULL)) { + /* the result must be valid UTF-8. */ + return NULL; + } + + return g_steal_pointer(&s); +} + +gboolean +nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val) +{ + gs_free char *str1_free = NULL; + const char * str1; + gs_free char *s = NULL; + + /* this is mostly the same as systemd's lease_parse_domain(). */ + + if (!nm_dhcp_lease_data_parse_cstr(data, n_data, &n_data)) + return FALSE; + + if (n_data == 0) { + /* empty domains are rejected. See + * https://tools.ietf.org/html/rfc2132#section-3.14 + * https://tools.ietf.org/html/rfc2132#section-3.17 + * + * Its minimum length is 1. + * + * Note that this is *after* we potentially stripped trailing NULs. + */ + return FALSE; + } + + str1 = nm_strndup_a(300, (char *) data, n_data, &str1_free); + + s = nm_dhcp_lease_data_parse_domain_validate(str1); + if (!s) + return FALSE; + + *out_val = g_steal_pointer(&s); + return TRUE; +} + +gboolean +nm_dhcp_lease_data_parse_in_addr(const guint8 *data, gsize n_data, in_addr_t *out_val) +{ + /* - option 1, https://tools.ietf.org/html/rfc2132#section-3.3 + * - option 28, https://tools.ietf.org/html/rfc2132#section-5.3 + */ + + if (n_data != 4) + return FALSE; + + *out_val = unaligned_read_ne32(data); + return TRUE; +} + +/*****************************************************************************/ + +static gboolean +lease_option_print_label(NMStrBuf *sbuf, size_t n_label, const uint8_t **datap, size_t *n_datap) +{ + gsize i; + + for (i = 0; i < n_label; ++i) { + uint8_t c = 0; + + if (!nm_dhcp_lease_data_consume(datap, n_datap, &c, sizeof(c))) + return FALSE; + + switch (c) { + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': + case '-': + case '_': + nm_str_buf_append_c(sbuf, c); + break; + case '.': + case '\\': + nm_str_buf_append_c2(sbuf, '\\', c); + break; + default: + nm_str_buf_append_printf(sbuf, "\\%3d", c); + } + } + + return TRUE; +} + +static char * +lease_option_print_domain_name(const uint8_t * cache, + size_t * n_cachep, + const uint8_t **datap, + size_t * n_datap) +{ + nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE); + const uint8_t * domain; + size_t n_domain; + size_t n_cache = *n_cachep; + const uint8_t ** domainp = datap; + size_t * n_domainp = n_datap; + gboolean first = TRUE; + uint8_t c; + + /* + * We are given two adjacent memory regions. The @cache contains alreday parsed + * domain names, and the @datap contains the remaining data to parse. + * + * A domain name is formed from a sequence of labels. Each label start with + * a length byte, where the two most significant bits are unset. A zero-length + * label indicates the end of the domain name. + * + * Alternatively, a label can be followed by an offset (indicated by the two + * most significant bits being set in the next byte that is read). The offset + * is an offset into the cache, where the next label of the domain name can + * be found. + * + * Note, that each time a jump to an offset is performed, the size of the + * cache shrinks, so this is guaranteed to terminate. + */ + if (cache + n_cache != *datap) + return NULL; + + for (;;) { + if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c))) + return NULL; + + switch (c & 0xC0) { + case 0x00: /* label length */ + { + size_t n_label = c; + + if (n_label == 0) { + /* + * We reached the final label of the domain name. Adjust + * the cache to include the consumed data, and return. + */ + *n_cachep = *datap - cache; + return nm_str_buf_finalize(&sbuf, NULL); + } + + if (!first) + nm_str_buf_append_c(&sbuf, '.'); + else + first = FALSE; + + if (!lease_option_print_label(&sbuf, n_label, domainp, n_domainp)) + return NULL; + + break; + } + case 0xC0: /* back pointer */ + { + size_t offset = (c & 0x3F) << 16; + + /* + * The offset is given as two bytes (in big endian), where the + * two high bits are masked out. + */ + + if (!nm_dhcp_lease_data_consume(domainp, n_domainp, &c, sizeof(c))) + return NULL; + + offset += c; + + if (offset >= n_cache) + return NULL; + + domain = cache + offset; + n_domain = n_cache - offset; + n_cache = offset; + + domainp = &domain; + n_domainp = &n_domain; + + break; + } + default: + return NULL; + } + } +} + +char ** +nm_dhcp_lease_data_parse_search_list(const guint8 *data, gsize n_data) +{ + GPtrArray * array = NULL; + const guint8 *cache = data; + gsize n_cache = 0; + + for (;;) { + gs_free char *s = NULL; + + s = lease_option_print_domain_name(cache, &n_cache, &data, &n_data); + if (!s) + break; + + if (!array) + array = g_ptr_array_new(); + + g_ptr_array_add(array, g_steal_pointer(&s)); + } + + if (!array) + return NULL; + + g_ptr_array_add(array, NULL); + return (char **) g_ptr_array_free(array, FALSE); +} diff --git a/src/dhcp/nm-dhcp-utils.h b/src/core/dhcp/nm-dhcp-utils.h index c72d9617..69715f90 100644 --- a/src/dhcp/nm-dhcp-utils.h +++ b/src/core/dhcp/nm-dhcp-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -36,8 +36,35 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family, const char *uuid, char ** out_leasefile_path); -char **nm_dhcp_parse_search_list(guint8 *data, size_t n_data); - char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease); +/*****************************************************************************/ + +static inline gboolean +nm_dhcp_lease_data_consume(const uint8_t **datap, size_t *n_datap, void *out, size_t n_out) +{ + if (*n_datap < n_out) + return FALSE; + + memcpy(out, *datap, n_out); + *datap += n_out; + *n_datap -= n_out; + return TRUE; +} + +static inline gboolean +nm_dhcp_lease_data_consume_in_addr(const uint8_t **datap, size_t *n_datap, in_addr_t *addrp) +{ + return nm_dhcp_lease_data_consume(datap, n_datap, addrp, sizeof(struct in_addr)); +} + +char *nm_dhcp_lease_data_parse_domain_validate(const char *str); + +gboolean nm_dhcp_lease_data_parse_u16(const guint8 *data, gsize n_data, guint16 *out_val); +gboolean nm_dhcp_lease_data_parse_mtu(const guint8 *data, gsize n_data, guint16 *out_val); +gboolean nm_dhcp_lease_data_parse_cstr(const guint8 *data, gsize n_data, gsize *out_new_len); +gboolean nm_dhcp_lease_data_parse_domain(const guint8 *data, gsize n_data, char **out_val); +gboolean nm_dhcp_lease_data_parse_in_addr(const guint8 *data, gsize n_data, in_addr_t *out_val); +char ** nm_dhcp_lease_data_parse_search_list(const guint8 *data, gsize n_data); + #endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ diff --git a/src/dhcp/tests/meson.build b/src/core/dhcp/tests/meson.build index 59a647cc..e43c8cab 100644 --- a/src/dhcp/tests/meson.build +++ b/src/core/dhcp/tests/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_units = [ 'test-dhcp-dhclient', @@ -9,7 +9,7 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/dhcp/tests/test-dhclient-commented-duid.leases b/src/core/dhcp/tests/test-dhclient-commented-duid.leases index 3e46ae7d..3e46ae7d 100644 --- a/src/dhcp/tests/test-dhclient-commented-duid.leases +++ b/src/core/dhcp/tests/test-dhclient-commented-duid.leases diff --git a/src/dhcp/tests/test-dhclient-duid.leases b/src/core/dhcp/tests/test-dhclient-duid.leases index 229331d4..229331d4 100644 --- a/src/dhcp/tests/test-dhclient-duid.leases +++ b/src/core/dhcp/tests/test-dhclient-duid.leases diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c index da24f3c5..77626f69 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/core/dhcp/tests/test-dhcp-dhclient.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <unistd.h> #include <arpa/inet.h> @@ -20,7 +20,7 @@ #include "nm-test-utils-core.h" -#define TEST_DIR NM_BUILD_SRCDIR "/src/dhcp/tests" +#define TEST_DIR NM_BUILD_SRCDIR "/src/core/dhcp/tests" #define TEST_MUDURL "https://example.com/mud.json" static void diff --git a/src/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c index 50245c79..9b54e2cd 100644 --- a/src/dhcp/tests/test-dhcp-utils.c +++ b/src/core/dhcp/tests/test-dhcp-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <netinet/in.h> #include <arpa/inet.h> @@ -13,10 +13,13 @@ #include "nm-utils.h" #include "dhcp/nm-dhcp-utils.h" +#include "dhcp/nm-dhcp-options.h" #include "platform/nm-platform.h" #include "nm-test-utils-core.h" +/*****************************************************************************/ + static NMIP4Config * _ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric) { @@ -202,7 +205,7 @@ test_parse_search_list(void) char ** domains; data = (guint8[]){0x05, 'l', 'o', 'c', 'a', 'l', 0x00}; - domains = nm_dhcp_parse_search_list(data, 7); + domains = nm_dhcp_lease_data_parse_search_list(data, 7); g_assert(domains); g_assert_cmpint(g_strv_length(domains), ==, 1); g_assert_cmpstr(domains[0], ==, "local"); @@ -211,7 +214,7 @@ test_parse_search_list(void) data = (guint8[]){0x04, 't', 'e', 's', 't', 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0x03, 'c', 'o', 'm', 0x00, 0xc0, 0x05, 0x03, 'a', 'b', 'c', 0xc0, 0x0d, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x00}; - domains = nm_dhcp_parse_search_list(data, 34); + domains = nm_dhcp_lease_data_parse_search_list(data, 34); g_assert(domains); g_assert_cmpint(g_strv_length(domains), ==, 4); g_assert_cmpstr(domains[0], ==, "test.example.com"); @@ -226,7 +229,7 @@ test_parse_search_list(void) 'a', 'd', }; - domains = nm_dhcp_parse_search_list(data, 4); + domains = nm_dhcp_lease_data_parse_search_list(data, 4); g_assert(!domains); data = (guint8[]){ @@ -241,7 +244,7 @@ test_parse_search_list(void) 'a', 'd', }; - domains = nm_dhcp_parse_search_list(data, 10); + domains = nm_dhcp_lease_data_parse_search_list(data, 10); g_assert(domains); g_assert_cmpint(g_strv_length(domains), ==, 1); g_assert_cmpstr(domains[0], ==, "okay"); @@ -740,6 +743,46 @@ test_client_id_from_string(void) COMPARE_ID(endcolon, TRUE, endcolon, strlen(endcolon)); } +/*****************************************************************************/ + +static void +test_dhcp_opt_list(gconstpointer test_data) +{ + const gboolean IS_IPv4 = (GPOINTER_TO_INT(test_data) == 0); + const int addr_family = IS_IPv4 ? AF_INET : AF_INET6; + const NMDhcpOption *const options = + IS_IPv4 ? _nm_dhcp_option_dhcp4_options : _nm_dhcp_option_dhcp6_options; + const guint n = (IS_IPv4 ? G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options) + : G_N_ELEMENTS(_nm_dhcp_option_dhcp6_options)); + guint i; + guint j; + + g_assert(options); + g_assert(n > 0); + + for (i = 0; i < n; i++) { + const NMDhcpOption *const opt = &options[i]; + + g_assert_cmpstr(opt->name, !=, NULL); + g_assert(NM_STR_HAS_PREFIX(opt->name, NM_DHCP_OPTION_REQPREFIX)); + + for (j = 0; j < i; j++) { + const NMDhcpOption *const opt2 = &options[j]; + + g_assert_cmpstr(opt->name, !=, opt2->name); + g_assert_cmpint(opt->option_num, !=, opt2->option_num); + } + } + + for (i = 0; i < n; i++) { + const NMDhcpOption *const opt = &options[i]; + + g_assert(opt == nm_dhcp_option_find(addr_family, opt->option_num)); + } +} + +/*****************************************************************************/ + NMTST_DEFINE(); int @@ -776,6 +819,8 @@ main(int argc, char **argv) g_test_add_func("/dhcp/client-id-from-string", test_client_id_from_string); g_test_add_func("/dhcp/vendor-option-metered", test_vendor_option_metered); g_test_add_func("/dhcp/parse-search-list", test_parse_search_list); + g_test_add_data_func("/dhcp/test_dhcp_opt_list/IPv4", GINT_TO_POINTER(0), test_dhcp_opt_list); + g_test_add_data_func("/dhcp/test_dhcp_opt_list/IPv6", GINT_TO_POINTER(1), test_dhcp_opt_list); return g_test_run(); } diff --git a/src/dns/nm-dns-dnsmasq.c b/src/core/dns/nm-dns-dnsmasq.c index 97f1dfab..dcff98e9 100644 --- a/src/dns/nm-dns-dnsmasq.c +++ b/src/core/dns/nm-dns-dnsmasq.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dns-dnsmasq.h" @@ -804,7 +804,7 @@ add_global_config(NMDnsDnsmasq * self, } static void -add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsIPConfigData *ip_data) +add_ip_config(NMDnsDnsmasq *self, GVariantBuilder *servers, const NMDnsConfigIPData *ip_data) { NMIPConfig * ip_config = ip_data->ip_config; gconstpointer addr; @@ -850,7 +850,7 @@ create_update_args(NMDnsDnsmasq * self, const char * hostname) { GVariantBuilder servers; - const NMDnsIPConfigData *ip_data; + const NMDnsConfigIPData *ip_data; g_variant_builder_init(&servers, G_VARIANT_TYPE("aas")); diff --git a/src/dns/nm-dns-dnsmasq.h b/src/core/dns/nm-dns-dnsmasq.h index d75eef55..bd6d4c60 100644 --- a/src/dns/nm-dns-dnsmasq.h +++ b/src/core/dns/nm-dns-dnsmasq.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/dns/nm-dns-manager.c b/src/core/dns/nm-dns-manager.c index 3fc9a396..f318b9b8 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/core/dns/nm-dns-manager.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com> * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <fcntl.h> #include <resolv.h> @@ -80,14 +80,18 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMDnsManager, PROP_MODE, PROP_RC_MANAGER, PROP_CONF static guint signals[LAST_SIGNAL] = {0}; typedef struct { - GHashTable *configs; - CList ip_config_lst_head; - GVariant * config_variant; + GHashTable *configs_dict; + CList configs_lst_head; - NMDnsIPConfigData *best_ip_config_4; - NMDnsIPConfigData *best_ip_config_6; + CList ip_configs_lst_head; + GVariant *config_variant; - bool ip_config_lst_need_sort : 1; + NMDnsConfigIPData *best_ip_config_4; + NMDnsConfigIPData *best_ip_config_6; + + bool ip_configs_lst_need_sort : 1; + + bool configs_lst_need_sort : 1; bool dns_touched : 1; bool is_stopped : 1; @@ -158,7 +162,7 @@ NM_DEFINE_SINGLETON_GETTER(NMDnsManager, nm_dns_manager_get, NM_TYPE_DNS_MANAGER /*****************************************************************************/ static void -_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsIPConfigData *ip_data); +_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data); /*****************************************************************************/ @@ -207,7 +211,7 @@ static NM_UTILS_LOOKUP_STR_DEFINE( /*****************************************************************************/ static void -_ASSERT_config_data(const NMDnsConfigData *data) +_ASSERT_dns_config_data(const NMDnsConfigData *data) { nm_assert(data); nm_assert(NM_IS_DNS_MANAGER(data->self)); @@ -215,10 +219,10 @@ _ASSERT_config_data(const NMDnsConfigData *data) } static void -_ASSERT_ip_config_data(const NMDnsIPConfigData *ip_data) +_ASSERT_dns_config_ip_data(const NMDnsConfigIPData *ip_data) { nm_assert(ip_data); - _ASSERT_config_data(ip_data->data); + _ASSERT_dns_config_data(ip_data->data); nm_assert(NM_IS_IP_CONFIG(ip_data->ip_config)); 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)); @@ -244,23 +248,25 @@ _ASSERT_ip_config_data(const NMDnsIPConfigData *ip_data) #endif } -static NMDnsIPConfigData * -_ip_config_data_new(NMDnsConfigData *data, NMIPConfig *ip_config, NMDnsIPConfigType ip_config_type) +static NMDnsConfigIPData * +_dns_config_ip_data_new(NMDnsConfigData * data, + NMIPConfig * ip_config, + NMDnsIPConfigType ip_config_type) { - NMDnsIPConfigData *ip_data; + NMDnsConfigIPData *ip_data; - _ASSERT_config_data(data); + _ASSERT_dns_config_data(data); nm_assert(NM_IS_IP_CONFIG(ip_config)); nm_assert(ip_config_type != NM_DNS_IP_CONFIG_TYPE_REMOVED); - ip_data = g_slice_new(NMDnsIPConfigData); - *ip_data = (NMDnsIPConfigData){ + ip_data = g_slice_new(NMDnsConfigIPData); + *ip_data = (NMDnsConfigIPData){ .data = data, .ip_config = g_object_ref(ip_config), .ip_config_type = ip_config_type, }; 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, + c_list_link_tail(&NM_DNS_MANAGER_GET_PRIVATE(data->self)->ip_configs_lst_head, &ip_data->ip_config_lst); g_signal_connect(ip_config, @@ -269,14 +275,14 @@ _ip_config_data_new(NMDnsConfigData *data, NMIPConfig *ip_config, NMDnsIPConfigT (GCallback) _ip_config_dns_priority_changed, ip_data); - _ASSERT_ip_config_data(ip_data); + _ASSERT_dns_config_ip_data(ip_data); return ip_data; } static void -_ip_config_data_free(NMDnsIPConfigData *ip_data) +_dns_config_ip_data_free(NMDnsConfigIPData *ip_data) { - _ASSERT_ip_config_data(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); @@ -292,15 +298,15 @@ _ip_config_data_free(NMDnsIPConfigData *ip_data) nm_g_slice_free(ip_data); } -static NMDnsIPConfigData * -_config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config) +static NMDnsConfigIPData * +_dns_config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config) { - NMDnsIPConfigData *ip_data; + NMDnsConfigIPData *ip_data; - _ASSERT_config_data(data); + _ASSERT_dns_config_data(data); c_list_for_each_entry (ip_data, &data->data_lst_head, data_lst) { - _ASSERT_ip_config_data(ip_data); + _ASSERT_dns_config_ip_data(ip_data); if (ip_data->ip_config == ip_config) return ip_data; @@ -309,19 +315,20 @@ _config_data_find_ip_config(NMDnsConfigData *data, NMIPConfig *ip_config) } static void -_config_data_free(NMDnsConfigData *data) +_dns_config_data_free(NMDnsConfigData *data) { - _ASSERT_config_data(data); + _ASSERT_dns_config_data(data); nm_assert(c_list_is_empty(&data->data_lst_head)); + c_list_unlink_stale(&data->configs_lst); nm_g_slice_free(data); } static int -_ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) +_mgr_get_ip_configs_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) { - const NMDnsIPConfigData *a = c_list_entry(a_lst, NMDnsIPConfigData, ip_config_lst); - const NMDnsIPConfigData *b = c_list_entry(b_lst, NMDnsIPConfigData, ip_config_lst); + const NMDnsConfigIPData *a = c_list_entry(a_lst, NMDnsConfigIPData, ip_config_lst); + const NMDnsConfigIPData *b = c_list_entry(b_lst, NMDnsConfigIPData, ip_config_lst); /* Configurations with lower priority value first */ NM_CMP_DIRECT(nm_ip_config_get_dns_priority(a->ip_config), @@ -334,16 +341,39 @@ _ip_config_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data } static CList * -_ip_config_lst_head(NMDnsManager *self) +_mgr_get_ip_configs_lst_head(NMDnsManager *self) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - if (priv->ip_config_lst_need_sort) { - priv->ip_config_lst_need_sort = FALSE; - c_list_sort(&priv->ip_config_lst_head, _ip_config_lst_cmp, NULL); + if (G_UNLIKELY(priv->ip_configs_lst_need_sort)) { + priv->ip_configs_lst_need_sort = FALSE; + c_list_sort(&priv->ip_configs_lst_head, _mgr_get_ip_configs_lst_cmp, NULL); } - return &priv->ip_config_lst_head; + return &priv->ip_configs_lst_head; +} + +static int +_mgr_get_configs_lst_cmp(const CList *a_lst, const CList *b_lst, const void *user_data) +{ + const NMDnsConfigData *a = c_list_entry(a_lst, NMDnsConfigData, configs_lst); + const NMDnsConfigData *b = c_list_entry(b_lst, NMDnsConfigData, configs_lst); + + NM_CMP_FIELD(b, a, ifindex); + return nm_assert_unreachable_val(0); +} + +_nm_unused static CList * +_mgr_get_configs_lst_head(NMDnsManager *self) +{ + NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); + + if (G_UNLIKELY(priv->configs_lst_need_sort)) { + priv->configs_lst_need_sort = FALSE; + c_list_sort(&priv->configs_lst_head, _mgr_get_configs_lst_cmp, NULL); + } + + return &priv->configs_lst_head; } /*****************************************************************************/ @@ -1077,7 +1107,7 @@ static void compute_hash(NMDnsManager *self, const NMGlobalDnsConfig *global, guint8 buffer[HASH_LEN]) { nm_auto_free_checksum GChecksum *sum = NULL; - NMDnsIPConfigData * ip_data; + NMDnsConfigIPData * ip_data; sum = g_checksum_new(G_CHECKSUM_SHA1); nm_assert(HASH_LEN == g_checksum_type_get_length(G_CHECKSUM_SHA1)); @@ -1089,7 +1119,7 @@ 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 = _ip_config_lst_head(self); + head = _mgr_get_ip_configs_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) nm_ip_config_hash(ip_data->ip_config, sum, TRUE); } @@ -1196,15 +1226,15 @@ _collect_resolv_conf_data(NMDnsManager * self, else { nm_auto_free_gstring GString *tmp_gstring = NULL; int prio, first_prio = 0; - const NMDnsIPConfigData * ip_data; + const NMDnsConfigIPData * ip_data; const CList * head; gboolean is_first = TRUE; - head = _ip_config_lst_head(self); + head = _mgr_get_ip_configs_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { gboolean skip = FALSE; - _ASSERT_ip_config_data(ip_data); + _ASSERT_dns_config_ip_data(ip_data); prio = nm_ip_config_get_dns_priority(ip_data->ip_config); @@ -1259,41 +1289,35 @@ _collect_resolv_conf_data(NMDnsManager * self, *out_nis_domain = rc.nis_domain; } +/*****************************************************************************/ + static char ** get_ip_rdns_domains(NMIPConfig *ip_config) { - int addr_family = nm_ip_config_get_addr_family(ip_config); - char ** strv; - GPtrArray * domains = NULL; - NMDedupMultiIter ipconf_iter; + 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); domains = g_ptr_array_sized_new(5); - if (addr_family == AF_INET) { - NMIP4Config * ip4 = (gpointer) ip_config; - const NMPlatformIP4Address *address; - const NMPlatformIP4Route * route; - - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &address) - nm_utils_get_reverse_dns_domains_ip4(address->address, address->plen, domains); - - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) - nm_utils_get_reverse_dns_domains_ip4(route->network, route->plen, domains); - } - } else { - NMIP6Config * ip6 = (gpointer) ip_config; - const NMPlatformIP6Address *address; - const NMPlatformIP6Route * route; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &address) - nm_utils_get_reverse_dns_domains_ip6(&address->address, address->plen, domains); + nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &address) { + nm_utils_get_reverse_dns_domains_ip(addr_family, + address->address_ptr, + address->plen, + domains); + } - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { - if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) - nm_utils_get_reverse_dns_domains_ip6(&route->network, route->plen, domains); + nm_ip_config_iter_ip_route_for_each (&ipconf_iter, ip_config, &route) { + if (!NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) { + nm_utils_get_reverse_dns_domains_ip(addr_family, + route->network_ptr, + route->plen, + domains); } } @@ -1307,7 +1331,7 @@ get_ip_rdns_domains(NMIPConfig *ip_config) } static gboolean -domain_ht_get_priority(GHashTable *ht, const char *domain, int *out_priority) +_domain_track_get_priority(GHashTable *ht, const char *domain, int *out_priority) { gpointer ptr; @@ -1321,11 +1345,11 @@ domain_ht_get_priority(GHashTable *ht, const char *domain, int *out_priority) /* Check if the domain is shadowed by a parent domain with more negative priority */ static gboolean -domain_is_shadowed(GHashTable * ht, - const char * domain, - int priority, - const char **out_parent, - int * out_parent_priority) +_domain_track_is_shadowed(GHashTable * ht, + const char * domain, + int priority, + const char **out_parent, + int * out_parent_priority) { char *parent; int parent_priority; @@ -1335,7 +1359,7 @@ domain_is_shadowed(GHashTable * ht, nm_assert(!g_hash_table_contains(ht, domain)); - if (domain_ht_get_priority(ht, "", &parent_priority)) { + if (_domain_track_get_priority(ht, "", &parent_priority)) { nm_assert(parent_priority <= priority); if (parent_priority < 0 && parent_priority < priority) { *out_parent = ""; @@ -1347,7 +1371,7 @@ domain_is_shadowed(GHashTable * ht, parent = strchr(domain, '.'); while (parent && parent[1]) { parent++; - if (domain_ht_get_priority(ht, parent, &parent_priority)) { + if (_domain_track_get_priority(ht, parent, &parent_priority)) { nm_assert(parent_priority <= priority); if (parent_priority < 0 && parent_priority < priority) { *out_parent = parent; @@ -1362,18 +1386,18 @@ domain_is_shadowed(GHashTable * ht, } static void -rebuild_domain_lists(NMDnsManager *self) +_mgr_configs_data_construct(NMDnsManager *self) { - NMDnsIPConfigData *ip_data; + NMDnsConfigIPData *ip_data; gs_unref_hashtable GHashTable *ht = NULL; gs_unref_hashtable GHashTable *wildcard_entries = NULL; CList * head; int prev_priority = G_MININT; - head = _ip_config_lst_head(self); + head = _mgr_get_ip_configs_lst_head(self); #if NM_MORE_ASSERTS - /* we call clear_domain_lists() at the end of update. We + /* 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) { nm_assert(!ip_data->domains.search); @@ -1496,7 +1520,7 @@ rebuild_domain_lists(NMDnsManager *self) break; /* Remove domains with lower priority */ - if (domain_ht_get_priority(ht, domain_clean, &old_priority)) { + if (_domain_track_get_priority(ht, domain_clean, &old_priority)) { nm_assert(old_priority <= priority); if (old_priority < priority) { _LOGT("plugin: drop domain %s%s%s (i=%d, p=%d) because it already exists " @@ -1511,7 +1535,11 @@ rebuild_domain_lists(NMDnsManager *self) old_priority); continue; } - } else if (domain_is_shadowed(ht, domain_clean, priority, &parent, &parent_priority)) { + } else if (_domain_track_is_shadowed(ht, + domain_clean, + priority, + &parent, + &parent_priority)) { _LOGT("plugin: drop domain %s%s%s (i=%d, p=%d) shadowed by '%s' (p=%d)", NM_PRINT_FMT_QUOTED(!check_default_route, "'", @@ -1578,12 +1606,12 @@ rebuild_domain_lists(NMDnsManager *self) } static void -clear_domain_lists(NMDnsManager *self) +_mgr_configs_data_clear(NMDnsManager *self) { - NMDnsIPConfigData *ip_data; + NMDnsConfigIPData *ip_data; CList * head; - head = _ip_config_lst_head(self); + head = _mgr_get_ip_configs_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { nm_clear_g_free(&ip_data->domains.search); nm_clear_pointer(&ip_data->domains.reverse, g_strfreev); @@ -1593,6 +1621,8 @@ clear_domain_lists(NMDnsManager *self) } } +/*****************************************************************************/ + static gboolean update_dns(NMDnsManager *self, gboolean no_caching, GError **error) { @@ -1645,12 +1675,12 @@ update_dns(NMDnsManager *self, gboolean no_caching, GError **error) &nis_domain); if (priv->plugin || priv->sd_resolve_plugin) - rebuild_domain_lists(self); + _mgr_configs_data_construct(self); if (priv->sd_resolve_plugin) { nm_dns_plugin_update(priv->sd_resolve_plugin, global_config, - _ip_config_lst_head(self), + _mgr_get_ip_configs_lst_head(self), priv->hostname, NULL); } @@ -1672,7 +1702,7 @@ update_dns(NMDnsManager *self, gboolean no_caching, GError **error) _LOGD("update-dns: updating plugin %s", plugin_name); if (!nm_dns_plugin_update(plugin, global_config, - _ip_config_lst_head(self), + _mgr_get_ip_configs_lst_head(self), priv->hostname, &plugin_error)) { _LOGW("update-dns: plugin %s update failed: %s", plugin_name, plugin_error->message); @@ -1689,7 +1719,7 @@ plugin_skip:; /* Clear the generated search list as it points to * strings owned by IP configurations and we can't * guarantee they stay alive. */ - clear_domain_lists(self); + _mgr_configs_data_clear(self); update_resolv_conf_no_stub(self, NM_CAST_STRV_CC(searches), @@ -1702,6 +1732,8 @@ plugin_skip:; */ if (caching) { const char *lladdr = "127.0.0.1"; + gboolean need_edns0; + gboolean need_trust; if (NM_IS_DNS_SYSTEMD_RESOLVED(priv->plugin)) { /* systemd-resolved uses a different link-local address */ @@ -1711,6 +1743,21 @@ plugin_skip:; g_strfreev(nameservers); nameservers = g_new0(char *, 2); nameservers[0] = g_strdup(lladdr); + + need_edns0 = nm_utils_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_EDNS0) < 0; + need_trust = nm_utils_strv_find_first(options, -1, NM_SETTING_DNS_OPTION_TRUST_AD) < 0; + + if (need_edns0 || need_trust) { + gsize len; + + len = NM_PTRARRAY_LEN(options); + options = g_realloc(options, sizeof(char *) * (len + 3u)); + if (need_edns0) + options[len++] = g_strdup(NM_SETTING_DNS_OPTION_EDNS0); + if (need_trust) + options[len++] = g_strdup(NM_SETTING_DNS_OPTION_TRUST_AD); + options[len] = NULL; + } } if (do_update) { @@ -1788,11 +1835,11 @@ plugin_skip:; /*****************************************************************************/ static void -_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsIPConfigData *ip_data) +_ip_config_dns_priority_changed(gpointer config, GParamSpec *pspec, NMDnsConfigIPData *ip_data) { - _ASSERT_ip_config_data(ip_data); + _ASSERT_dns_config_ip_data(ip_data); - NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_config_lst_need_sort = TRUE; + NM_DNS_MANAGER_GET_PRIVATE(ip_data->data->self)->ip_configs_lst_need_sort = TRUE; } gboolean @@ -1801,10 +1848,10 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, NMDnsIPConfigType ip_config_type) { NMDnsManagerPrivate *priv; - NMDnsIPConfigData * ip_data; + NMDnsConfigIPData * ip_data; NMDnsConfigData * data; int ifindex; - NMDnsIPConfigData ** p_best; + NMDnsConfigIPData ** p_best; g_return_val_if_fail(NM_IS_DNS_MANAGER(self), FALSE); g_return_val_if_fail(NM_IS_IP_CONFIG(ip_config), FALSE); @@ -1814,11 +1861,11 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, priv = NM_DNS_MANAGER_GET_PRIVATE(self); - data = g_hash_table_lookup(priv->configs, &ifindex); + data = g_hash_table_lookup(priv->configs_dict, &ifindex); if (!data) ip_data = NULL; else - ip_data = _config_data_find_ip_config(data, ip_config); + ip_data = _dns_config_data_find_ip_config(data, ip_config); if (ip_config_type == NM_DNS_IP_CONFIG_TYPE_REMOVED) { if (!ip_data) @@ -1828,9 +1875,9 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, if (priv->best_ip_config_6 == ip_data) priv->best_ip_config_6 = NULL; /* deleting a config doesn't invalidate the configs' sort order. */ - _ip_config_data_free(ip_data); + _dns_config_ip_data_free(ip_data); if (c_list_is_empty(&data->data_lst_head)) - g_hash_table_remove(priv->configs, &ifindex); + g_hash_table_remove(priv->configs_dict, &ifindex); goto changed; } @@ -1846,16 +1893,18 @@ nm_dns_manager_set_ip_config(NMDnsManager * self, .self = self, .data_lst_head = C_LIST_INIT(data->data_lst_head), }; - _ASSERT_config_data(data); - g_hash_table_add(priv->configs, data); + _ASSERT_dns_config_data(data); + g_hash_table_add(priv->configs_dict, data); + c_list_link_tail(&priv->configs_lst_head, &data->configs_lst); + priv->configs_lst_need_sort = TRUE; } if (!ip_data) - ip_data = _ip_config_data_new(data, ip_config, ip_config_type); + ip_data = _dns_config_ip_data_new(data, ip_config, ip_config_type); else ip_data->ip_config_type = ip_config_type; - priv->ip_config_lst_need_sort = TRUE; + priv->ip_configs_lst_need_sort = TRUE; p_best = NM_IS_IP4_CONFIG(ip_config) ? &priv->best_ip_config_4 : &priv->best_ip_config_6; @@ -2375,7 +2424,7 @@ _get_config_variant(NMDnsManager *self) NMGlobalDnsConfig * global_config; gs_free char * str = NULL; GVariantBuilder builder; - NMDnsIPConfigData * ip_data; + NMDnsConfigIPData * ip_data; const CList * head; gs_unref_ptrarray GPtrArray *array_domains = NULL; @@ -2391,7 +2440,7 @@ _get_config_variant(NMDnsManager *self) g_variant_builder_init(&builder, G_VARIANT_TYPE("aa{sv}")); - head = _ip_config_lst_head(self); + head = _mgr_get_ip_configs_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; @@ -2496,15 +2545,16 @@ nm_dns_manager_init(NMDnsManager *self) _LOGT("creating..."); - c_list_init(&priv->ip_config_lst_head); + c_list_init(&priv->configs_lst_head); + c_list_init(&priv->ip_configs_lst_head); priv->config = g_object_ref(nm_config_get()); G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDnsConfigData, ifindex) == 0); - priv->configs = g_hash_table_new_full(nm_pint_hash, - nm_pint_equals, - (GDestroyNotify) _config_data_free, - NULL); + priv->configs_dict = g_hash_table_new_full(nm_pint_hash, + nm_pint_equals, + (GDestroyNotify) _dns_config_data_free, + NULL); /* Set the initial hash */ compute_hash(self, NULL, NM_DNS_MANAGER_GET_PRIVATE(self)->hash); @@ -2521,7 +2571,7 @@ dispose(GObject *object) { NMDnsManager * self = NM_DNS_MANAGER(object); NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE(self); - NMDnsIPConfigData * ip_data, *ip_data_safe; + NMDnsConfigIPData * ip_data, *ip_data_safe; _LOGT("disposing"); @@ -2537,10 +2587,11 @@ dispose(GObject *object) priv->best_ip_config_4 = NULL; priv->best_ip_config_6 = NULL; - c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_config_lst_head, ip_config_lst) - _ip_config_data_free(ip_data); + c_list_for_each_entry_safe (ip_data, ip_data_safe, &priv->ip_configs_lst_head, ip_config_lst) + _dns_config_ip_data_free(ip_data); - nm_clear_pointer(&priv->configs, g_hash_table_destroy); + nm_clear_pointer(&priv->configs_dict, g_hash_table_destroy); + nm_assert(c_list_is_empty(&priv->configs_lst_head)); nm_clear_g_source(&priv->plugin_ratelimit.timer); diff --git a/src/dns/nm-dns-manager.h b/src/core/dns/nm-dns-manager.h index fb2f36d2..937ba62a 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/core/dns/nm-dns-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com> * Copyright (C) 2004 - 2013 Red Hat, Inc. @@ -25,6 +25,8 @@ enum { NM_DNS_PRIORITY_DEFAULT_VPN = 50, }; +/*****************************************************************************/ + struct _NMDnsConfigData; struct _NMDnsManager; @@ -60,14 +62,17 @@ typedef struct { * With systemd-resolved, this is the value for SetLinkDefaultRoute(). */ bool has_default_route : 1; } domains; -} NMDnsIPConfigData; +} NMDnsConfigIPData; typedef struct _NMDnsConfigData { int ifindex; struct _NMDnsManager *self; CList data_lst_head; + CList configs_lst; } NMDnsConfigData; +/*****************************************************************************/ + #define NM_TYPE_DNS_MANAGER (nm_dns_manager_get_type()) #define NM_DNS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST((o), NM_TYPE_DNS_MANAGER, NMDnsManager)) #define NM_DNS_MANAGER_CLASS(k) \ diff --git a/src/dns/nm-dns-plugin.c b/src/core/dns/nm-dns-plugin.c index e59feb3f..74d4eb2b 100644 --- a/src/dns/nm-dns-plugin.c +++ b/src/core/dns/nm-dns-plugin.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2012 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dns-plugin.h" diff --git a/src/dns/nm-dns-plugin.h b/src/core/dns/nm-dns-plugin.h index 5e87f59b..644d01e5 100644 --- a/src/dns/nm-dns-plugin.h +++ b/src/core/dns/nm-dns-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ @@ -26,7 +26,7 @@ typedef struct { GObjectClass parent; /* Called when DNS information is changed. 'configs' is an array - * of pointers to NMDnsIPConfigData sorted by priority. + * of pointers to NMDnsConfigIPData sorted by priority. * 'global_config' is the optional global DNS * configuration. */ diff --git a/src/dns/nm-dns-systemd-resolved.c b/src/core/dns/nm-dns-systemd-resolved.c index fe2e78af..f6e116f3 100644 --- a/src/dns/nm-dns-systemd-resolved.c +++ b/src/core/dns/nm-dns-systemd-resolved.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> * Copyright (C) 2016 Sjoerd Simons <sjoerd@luon.net> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dns-systemd-resolved.h" @@ -179,7 +179,7 @@ static gboolean update_add_ip_config(NMDnsSystemdResolved *self, GVariantBuilder * dns, GVariantBuilder * domains, - NMDnsIPConfigData * data) + NMDnsConfigIPData * data) { int addr_family; gsize addr_size; @@ -256,7 +256,7 @@ 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) { - NMDnsIPConfigData *data = elem->data; + NMDnsConfigIPData *data = elem->data; NMIPConfig * ip_config = data->ip_config; has_config |= update_add_ip_config(self, &dns, &domains, data); @@ -423,7 +423,7 @@ update(NMDnsPlugin * plugin, guint interfaces_len; int ifindex; gpointer pointer; - NMDnsIPConfigData *ip_data; + NMDnsConfigIPData *ip_data; GHashTableIter iter; guint i; diff --git a/src/dns/nm-dns-systemd-resolved.h b/src/core/dns/nm-dns-systemd-resolved.h index ed2528ea..4ab04ab4 100644 --- a/src/dns/nm-dns-systemd-resolved.h +++ b/src/core/dns/nm-dns-systemd-resolved.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. * Copyright (C) 2016 Sjoerd Simons <sjoerd@luon.net> diff --git a/src/dns/nm-dns-unbound.c b/src/core/dns/nm-dns-unbound.c index b9124759..15df3acf 100644 --- a/src/dns/nm-dns-unbound.c +++ b/src/core/dns/nm-dns-unbound.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. * Author: Pavel Å imerda <psimerda@redhat.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dns-unbound.h" diff --git a/src/dns/nm-dns-unbound.h b/src/core/dns/nm-dns-unbound.h index 4129ba9e..feb33099 100644 --- a/src/dns/nm-dns-unbound.h +++ b/src/core/dns/nm-dns-unbound.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/dnsmasq/nm-dnsmasq-manager.c b/src/core/dnsmasq/nm-dnsmasq-manager.c index 2dd4afcb..82c002b0 100644 --- a/src/dnsmasq/nm-dnsmasq-manager.c +++ b/src/core/dnsmasq/nm-dnsmasq-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2012 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dnsmasq-manager.h" @@ -313,7 +313,7 @@ nm_dnsmasq_manager_new(const char *iface) NMDnsMasqManager * manager; NMDnsMasqManagerPrivate *priv; - manager = (NMDnsMasqManager *) g_object_new(NM_TYPE_DNSMASQ_MANAGER, NULL); + manager = g_object_new(NM_TYPE_DNSMASQ_MANAGER, NULL); priv = NM_DNSMASQ_MANAGER_GET_PRIVATE(manager); priv->iface = g_strdup(iface); diff --git a/src/dnsmasq/nm-dnsmasq-manager.h b/src/core/dnsmasq/nm-dnsmasq-manager.h index 4f8b3055..272d1cea 100644 --- a/src/dnsmasq/nm-dnsmasq-manager.h +++ b/src/core/dnsmasq/nm-dnsmasq-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/dnsmasq/nm-dnsmasq-utils.c b/src/core/dnsmasq/nm-dnsmasq-utils.c index 3e430590..ea23a78d 100644 --- a/src/dnsmasq/nm-dnsmasq-utils.c +++ b/src/core/dnsmasq/nm-dnsmasq-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <arpa/inet.h> diff --git a/src/dnsmasq/nm-dnsmasq-utils.h b/src/core/dnsmasq/nm-dnsmasq-utils.h index 321035bd..57bbc4c4 100644 --- a/src/dnsmasq/nm-dnsmasq-utils.h +++ b/src/core/dnsmasq/nm-dnsmasq-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/dnsmasq/tests/meson.build b/src/core/dnsmasq/tests/meson.build index 4584086e..565c18ad 100644 --- a/src/dnsmasq/tests/meson.build +++ b/src/core/dnsmasq/tests/meson.build @@ -1,11 +1,11 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_unit = 'test-dnsmasq-utils' exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/dnsmasq/tests/test-dnsmasq-utils.c b/src/core/dnsmasq/tests/test-dnsmasq-utils.c index 4fa17576..4c1279f0 100644 --- a/src/dnsmasq/tests/test-dnsmasq-utils.c +++ b/src/core/dnsmasq/tests/test-dnsmasq-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <arpa/inet.h> diff --git a/src/core/initrd/meson.build b/src/core/initrd/meson.build new file mode 100644 index 00000000..bd590e8c --- /dev/null +++ b/src/core/initrd/meson.build @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +libnmi_core = static_library( + 'nmi-core', + sources: files( + 'nmi-cmdline-reader.c', + 'nmi-dt-reader.c', + 'nmi-ibft-reader.c', + ), + dependencies: core_default_dep, + c_args: daemon_c_flags, +) + +executable( + 'nm-initrd-generator', + 'nm-initrd-generator.c', + dependencies: core_default_dep, + c_args: daemon_c_flags, + link_with: [ + libNetworkManagerBase, + libnmi_core, + ], + link_args: ldflags_linker_script_binary, + link_depends: linker_script_binary, + install: true, + install_dir: nm_libexecdir, +) + +if enable_tests + subdir('tests') +endif diff --git a/src/initrd/nm-initrd-generator.c b/src/core/initrd/nm-initrd-generator.c index 1a33713e..18c7258a 100644 --- a/src/initrd/nm-initrd-generator.c +++ b/src/core/initrd/nm-initrd-generator.c @@ -1,14 +1,15 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-core-utils.h" #include "nm-core-internal.h" -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "nm-initrd-generator.h" #include "nm-glib-aux/nm-io-utils.h" +#include "nm-config.h" /*****************************************************************************/ @@ -63,6 +64,7 @@ err_out: #define DEFAULT_SYSFS_DIR "/sys" #define DEFAULT_INITRD_DATA_DIR NMRUNDIR "/initrd" +#define DEFAULT_RUN_CONFIG_DIR NMRUNDIR "/conf.d" int main(int argc, char *argv[]) @@ -71,6 +73,7 @@ main(int argc, char *argv[]) gs_free char * connections_dir = NULL; gs_free char * initrd_dir = NULL; gs_free char * sysfs_dir = NULL; + gs_free char * run_config_dir = NULL; gboolean dump_to_stdout = FALSE; gs_strfreev char **remaining = NULL; GOptionEntry option_entries[] = { @@ -95,6 +98,13 @@ main(int argc, char *argv[]) &sysfs_dir, "The sysfs mount point", DEFAULT_SYSFS_DIR}, + {"run-config-dir", + 'r', + 0, + G_OPTION_ARG_FILENAME, + &run_config_dir, + "Output config directory", + DEFAULT_RUN_CONFIG_DIR}, {"stdout", 's', 0, @@ -108,11 +118,12 @@ main(int argc, char *argv[]) gs_free_error GError *error = NULL; gs_free char * hostname = NULL; int errsv; + gint64 carrier_timeout_sec = 0; option_context = g_option_context_new( "-- [ip=...] [rd.route=...] [bridge=...] [bond=...] [team=...] [vlan=...] " "[bootdev=...] [nameserver=...] [rd.peerdns=...] [rd.bootif=...] [BOOTIF=...] " - "[rd.znet=...] ... "); + "[rd.znet=...] [rd.net.timeout.carrier=...] ... "); g_option_context_set_summary(option_context, "Generate early NetworkManager configuration."); g_option_context_set_description( @@ -138,29 +149,39 @@ main(int argc, char *argv[]) sysfs_dir = g_strdup(DEFAULT_SYSFS_DIR); if (!initrd_dir) initrd_dir = g_strdup(DEFAULT_INITRD_DATA_DIR); - if (dump_to_stdout) - nm_clear_g_free(&connections_dir); - - if (connections_dir && g_mkdir_with_parents(connections_dir, 0755) != 0) { - errsv = errno; - _LOGW(LOGD_CORE, "%s: %s", connections_dir, nm_strerror_native(errsv)); - return 1; - } + if (!run_config_dir) + run_config_dir = g_strdup(DEFAULT_RUN_CONFIG_DIR); - connections = nmi_cmdline_reader_parse(sysfs_dir, (const char *const *) remaining, &hostname); - - g_hash_table_foreach(connections, output_conn, connections_dir); - g_hash_table_destroy(connections); + connections = nmi_cmdline_reader_parse(sysfs_dir, + (const char *const *) remaining, + &hostname, + &carrier_timeout_sec); if (dump_to_stdout) { + nm_clear_g_free(&connections_dir); + nm_clear_g_free(&initrd_dir); + nm_clear_g_free(&run_config_dir); if (hostname) g_print("\n*** Hostname '%s' ***\n", hostname); + if (carrier_timeout_sec != 0) + g_print("\n*** Carrier Wait Timeout %" G_GINT64_FORMAT " sec ***\n", + carrier_timeout_sec); } else { + if (g_mkdir_with_parents(connections_dir, 0755) != 0) { + errsv = errno; + _LOGW(LOGD_CORE, "%s: %s", connections_dir, nm_strerror_native(errsv)); + return 1; + } if (g_mkdir_with_parents(initrd_dir, 0755) != 0) { errsv = errno; _LOGW(LOGD_CORE, "%s: %s", initrd_dir, nm_strerror_native(errsv)); return 1; } + if (g_mkdir_with_parents(run_config_dir, 0755) != 0) { + errsv = errno; + _LOGW(LOGD_CORE, "%s: %s", run_config_dir, nm_strerror_native(errsv)); + return 1; + } if (hostname) { gs_free char *hostname_file = NULL; @@ -174,7 +195,32 @@ main(int argc, char *argv[]) return 1; } } + if (carrier_timeout_sec != 0) { + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_free char * filename = NULL; + + keyfile = g_key_file_new(); + g_key_file_set_list_separator(keyfile, NM_CONFIG_KEYFILE_LIST_SEPARATOR); + filename = g_strdup_printf("%s/15-carrier-timeout.conf", run_config_dir); + + g_key_file_set_value(keyfile, + NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "-15-carrier-timeout", + NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, + "*"); + g_key_file_set_int64(keyfile, + NM_CONFIG_KEYFILE_GROUPPREFIX_DEVICE "-15-carrier-timeout", + NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT, + carrier_timeout_sec * 1000); + + if (!g_key_file_save_to_file(keyfile, filename, &error)) { + _LOGW(LOGD_CORE, "%s: %s", filename, error->message); + return 1; + } + } } + g_hash_table_foreach(connections, output_conn, connections_dir); + g_hash_table_destroy(connections); + return 0; } diff --git a/src/initrd/nm-initrd-generator.h b/src/core/initrd/nm-initrd-generator.h index 69c24b1b..56dcfd68 100644 --- a/src/initrd/nm-initrd-generator.h +++ b/src/core/initrd/nm-initrd-generator.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014, 2018 Red Hat, Inc. */ @@ -37,7 +37,9 @@ nmi_ibft_update_connection_from_nic(NMConnection *connection, GHashTable *nic, G NMConnection *nmi_dt_reader_parse(const char *sysfs_dir); -GHashTable * -nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char **hostname); +GHashTable *nmi_cmdline_reader_parse(const char * sysfs_dir, + const char *const *argv, + char ** hostname, + gint64 * carrier_timeout_sec); #endif /* __NM_INITRD_GENERATOR_H__ */ diff --git a/src/initrd/nmi-cmdline-reader.c b/src/core/initrd/nmi-cmdline-reader.c index 1c1b43eb..d95b0f9b 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/core/initrd/nmi-cmdline-reader.c @@ -1,9 +1,12 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" + +#include <linux/if_ether.h> +#include <linux/if_infiniband.h> #include "nm-core-internal.h" #include "nm-initrd-generator.h" @@ -34,6 +37,8 @@ typedef struct { gboolean ignore_auto_dns; int dhcp_timeout; char * dhcp4_vci; + + gint64 carrier_timeout_sec; } Reader; static Reader * @@ -416,7 +421,7 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) tmp = get_word(&argument, ':'); if (!*argument) { - /* ip={dhcp|on|any|dhcp6|auto6|ibft} */ + /* ip={dhcp|on|any|dhcp6|auto6|link6|ibft} */ kind = tmp; } else { tmp2 = get_word(&argument, ':'); @@ -429,8 +434,9 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) "dhcp6", "auto", "auto6", + "link6", "ibft")) { - /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|ibft} */ + /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|link6|ibft} */ iface_spec = tmp; kind = tmp2; } else { @@ -598,6 +604,19 @@ reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument) NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NULL); } + } else if (nm_streq0(kind, "link6")) { + g_object_set(s_ip6, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP_CONFIG_MAY_FAIL, + FALSE, + NULL); + if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) { + g_object_set(s_ip4, + NM_SETTING_IP_CONFIG_METHOD, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NULL); + } } else if (nm_streq0(kind, "ibft")) { NMSettingWired *s_wired; const char * mac = NULL; @@ -701,8 +720,6 @@ reader_parse_master(Reader *reader, char *argument, const char *type_name, const char * slaves; const char * slave; char * opts; - char * opt; - const char * opt_name; const char * mtu = NULL; master = get_word(&argument, ':'); @@ -724,8 +741,21 @@ reader_parse_master(Reader *reader, char *argument, const char *type_name, const opts = get_word(&argument, ':'); while (opts && *opts) { + gs_free_error GError *error = NULL; + char * opt; + const char * opt_name; + opt = get_word(&opts, ','); opt_name = get_word(&opt, '='); + + if (!_nm_setting_bond_validate_option(opt_name, opt, &error)) { + _LOGW(LOGD_CORE, + "Ignoring invalid bond option: %s%s%s = %s%s%s: %s", + NM_PRINT_FMT_QUOTE_STRING(opt_name), + NM_PRINT_FMT_QUOTE_STRING(opt), + error->message); + continue; + } nm_setting_bond_add_option(s_bond, opt_name, opt); } @@ -1019,7 +1049,10 @@ connection_set_needed_cb(gpointer key, gpointer value, gpointer user_data) } GHashTable * -nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char **hostname) +nmi_cmdline_reader_parse(const char * sysfs_dir, + const char *const *argv, + char ** hostname, + gint64 * carrier_timeout_sec) { Reader * reader; const char * tag; @@ -1053,6 +1086,9 @@ nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char ** } else if (nm_streq(tag, "rd.net.dhcp.vendor-class")) { if (nm_utils_validate_dhcp4_vendor_class_id(argument, NULL)) nm_utils_strdup_reset(&reader->dhcp4_vci, argument); + } else if (nm_streq(tag, "rd.net.timeout.carrier")) { + reader->carrier_timeout_sec = + _nm_utils_ascii_str_to_int64(argument, 10, 0, G_MAXINT32, 0); } } @@ -1140,14 +1176,21 @@ nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char ** NMConnection * connection; NMSettingWired *s_wired; const char * bootif = bootif_val; - - if (!nm_utils_hwaddr_valid(bootif, ETH_ALEN) && g_str_has_prefix(bootif, "01-") - && nm_utils_hwaddr_valid(&bootif[3], ETH_ALEN)) { - /* - * BOOTIF MAC address can be prefixed with a hardware type identifier. - * "01" stays for "wired", no other are known. - */ - bootif += 3; + char prefix[4]; + + if (!nm_utils_hwaddr_valid(bootif, ETH_ALEN)) { + strncpy(prefix, bootif, 3); + prefix[3] = '\0'; + + if (NM_IN_STRSET(prefix, "01-", "01:", "00-", "00:") + && nm_utils_hwaddr_valid(&bootif[3], ETH_ALEN)) { + /* + * BOOTIF MAC address can be prefixed with a hardware type identifier. + * "01" stays for "wired", "00" is also accepted as it means "undefined". + * No others are known. + */ + bootif += 3; + } } connection = reader_get_connection(reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE); @@ -1206,5 +1249,7 @@ nmi_cmdline_reader_parse(const char *sysfs_dir, const char *const *argv, char ** NM_SET_OUT(hostname, g_steal_pointer(&reader->hostname)); + NM_SET_OUT(carrier_timeout_sec, reader->carrier_timeout_sec); + return reader_destroy(reader, FALSE); } diff --git a/src/initrd/nmi-dt-reader.c b/src/core/initrd/nmi-dt-reader.c index 3039d902..63e4524b 100644 --- a/src/initrd/nmi-dt-reader.c +++ b/src/core/initrd/nmi-dt-reader.c @@ -1,13 +1,14 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-initrd-generator.h" #include <arpa/inet.h> +#include <linux/if_ether.h> #include "nm-core-internal.h" diff --git a/src/initrd/nmi-ibft-reader.c b/src/core/initrd/nmi-ibft-reader.c index b7ce4671..9895cda4 100644 --- a/src/initrd/nmi-ibft-reader.c +++ b/src/core/initrd/nmi-ibft-reader.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-initrd-generator.h" @@ -15,6 +15,7 @@ #include <sys/inotify.h> #include <sys/ioctl.h> #include <unistd.h> +#include <linux/if_ether.h> #include "nm-core-internal.h" #include "NetworkManagerUtils.h" diff --git a/src/initrd/tests/meson.build b/src/core/initrd/tests/meson.build index 1d0908b9..e47ff790 100644 --- a/src/initrd/tests/meson.build +++ b/src/core/initrd/tests/meson.build @@ -1,6 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -c_flags = test_c_flags + ['-DTEST_INITRD_DIR="@0@"'.format(meson.current_source_dir())] +# SPDX-License-Identifier: LGPL-2.1-or-later test_units = [ 'test-dt-reader', @@ -12,8 +10,8 @@ foreach test_unit : test_units exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, - c_args: c_flags, + dependencies: libNetworkManagerTest_dep, + c_args: test_c_flags, link_with: libnmi_core, ) diff --git a/src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-dns1/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-bad-dns1/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway index bf6cf454..bf6cf454 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr index 944c8d45..944c8d45 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len index 8fdd954d..8fdd954d 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns index 2303dbdc..2303dbdc 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask index 7cb9d0a9..7cb9d0a9 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-bad-dns1/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-dns2/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-bad-dns2/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway index bf6cf454..bf6cf454 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr index 944c8d45..944c8d45 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len index 8fdd954d..8fdd954d 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns index 5ed7b719..5ed7b719 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask index 7cb9d0a9..7cb9d0a9 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-bad-dns2/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-gateway/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-bad-gateway/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway index 1970856e..1970856e 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr index 944c8d45..944c8d45 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len index 8fdd954d..8fdd954d 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask index 7cb9d0a9..7cb9d0a9 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-bad-gateway/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address b/src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway index bf6cf454..bf6cf454 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr index d526f324..d526f324 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len index 8fdd954d..8fdd954d 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask index 7cb9d0a9..7cb9d0a9 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-bad-ipaddr/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-dhcp/class/net/eth0/address b/src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-dhcp/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-dhcp/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-dhcp/class/net/eth1/address b/src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address index befa7850..befa7850 100644 --- a/src/initrd/tests/sysfs-dhcp/class/net/eth1/address +++ b/src/core/initrd/tests/sysfs-dhcp/class/net/eth1/address diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway index 59ea5b82..59ea5b82 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin index e440e5c8..e440e5c8 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway index 59ea5b82..59ea5b82 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/gateway diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/index diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac index befa7850..befa7850 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/mac diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin index e440e5c8..e440e5c8 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/origin diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/primary-dns diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/secondary-dns diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/ethernet1/vlan diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/index diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/ip-addr diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/lun diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/port diff --git a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name index ac3a6a2a..ac3a6a2a 100644 --- a/src/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name +++ b/src/core/initrd/tests/sysfs-dhcp/firmware/ibft/target1/target-name diff --git a/src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath b/src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath index 6f069ae0..6f069ae0 100644 --- a/src/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath +++ b/src/core/initrd/tests/sysfs-dt-tftp/firmware/devicetree/base/chosen/bootpath Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request index 034d423e..034d423e 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-request Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response index 25982d6f..25982d6f 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootp-response Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath index db880702..db880702 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/bootpath Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip index 7bde8641..7bde8641 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/broadcast-ip diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip index f108ba9b..f108ba9b 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-ip diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name index fe0f76b8..fe0f76b8 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/client-name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name index b34f9f96..b34f9f96 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/domain-name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip index f0361835..f0361835 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/gateway-ip diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name index f3e58052..f3e58052 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/name Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip index d441cd83..d441cd83 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/netmask-ip Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path index f76dd238..f76dd238 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/root-path Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip index a2a4b2e8..a2a4b2e8 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/server-ip diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file index c0e0e330..c0e0e330 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/tftp-file Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options index f76dd238..f76dd238 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/chosen/vendor-options Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type index df3c9d9f..df3c9d9f 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/device_type Binary files differdiff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address index c983e752..c983e752 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/local-mac-address diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address index c983e752..c983e752 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/mac-address diff --git a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name index 88eaddfe..88eaddfe 100644 --- a/src/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name +++ b/src/core/initrd/tests/sysfs-dt/firmware/devicetree/base/ethernet/name Binary files differdiff --git a/src/initrd/tests/sysfs-static/class/net/eth0/address b/src/core/initrd/tests/sysfs-static/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-static/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-static/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-static/class/net/eth1/address b/src/core/initrd/tests/sysfs-static/class/net/eth1/address index befa7850..befa7850 100644 --- a/src/initrd/tests/sysfs-static/class/net/eth1/address +++ b/src/core/initrd/tests/sysfs-static/class/net/eth1/address diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway index bf6cf454..bf6cf454 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr index 944c8d45..944c8d45 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len index 8fdd954d..8fdd954d 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask index 7cb9d0a9..7cb9d0a9 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway index 59ea5b82..59ea5b82 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/gateway diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/index diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac index befa7850..befa7850 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/mac diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin index e440e5c8..e440e5c8 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/origin diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns index 2e152cb0..2e152cb0 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/primary-dns diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns index 2eb9e1d0..2eb9e1d0 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/secondary-dns diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/ethernet1/vlan diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name index 509a7ab8..509a7ab8 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name index 32c9450a..32c9450a 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/index b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target1/index +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/index diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr index 7450fdf9..7450fdf9 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/ip-addr diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/lun b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun index c43d0930..c43d0930 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target1/lun +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/lun diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/port b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target1/port +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/port diff --git a/src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name index ac3a6a2a..ac3a6a2a 100644 --- a/src/initrd/tests/sysfs-static/firmware/ibft/target1/target-name +++ b/src/core/initrd/tests/sysfs-static/firmware/ibft/target1/target-name diff --git a/src/initrd/tests/sysfs-vlan/class/net/eth0/address b/src/core/initrd/tests/sysfs-vlan/class/net/eth0/address index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-vlan/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs-vlan/class/net/eth0/address diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr index 4923230c..4923230c 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac index 20659db7..20659db7 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin index 56a6051c..56a6051c 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len index cabf43b5..cabf43b5 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask index 5a279b41..5a279b41 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan index d800886d..d800886d 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name index 8e9cd2c4..8e9cd2c4 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index index c2270834..c2270834 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr index a32ce01b..a32ce01b 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun index f309ca6a..f309ca6a 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port index 58f0d919..58f0d919 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name index f0e61157..f0e61157 100644 --- a/src/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name +++ b/src/core/initrd/tests/sysfs-vlan/firmware/ibft/target0/target-name diff --git a/src/initrd/tests/sysfs/class/net/eth0/address b/src/core/initrd/tests/sysfs/class/net/eth0/address index 1f2f610e..1f2f610e 100644 --- a/src/initrd/tests/sysfs/class/net/eth0/address +++ b/src/core/initrd/tests/sysfs/class/net/eth0/address diff --git a/src/initrd/tests/sysfs/class/net/eth2/address b/src/core/initrd/tests/sysfs/class/net/eth2/address index 6ec1078a..6ec1078a 100644 --- a/src/initrd/tests/sysfs/class/net/eth2/address +++ b/src/core/initrd/tests/sysfs/class/net/eth2/address diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id index 590d9cd2..590d9cd2 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id +++ b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_id diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id index 35d4d09c..35d4d09c 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id +++ b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/oem_table_id diff --git a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature index e3a5d7ef..e3a5d7ef 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/acpi_header/signature +++ b/src/core/initrd/tests/sysfs/firmware/ibft/acpi_header/signature diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp index 98a0d797..98a0d797 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/dhcp diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/flags +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/flags diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway index 7f378f8f..7f378f8f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/gateway diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname index 3ed5163c..3ed5163c 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/hostname diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/index b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/index +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/index diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr index 98a0d797..98a0d797 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/ip-addr diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac index f2441319..f2441319 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/mac +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/mac diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin index b8626c4c..b8626c4c 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/origin +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/origin diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len index 900731ff..900731ff 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/prefix-len diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns index e7511d5a..e7511d5a 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/primary-dns diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns index 1f6c5c95..1f6c5c95 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/secondary-dns diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask index 5df93454..5df93454 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/subnet-mask diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan index 7cc86ad1..7cc86ad1 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet0/vlan diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp index 61ef5585..61ef5585 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/dhcp diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/flags +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/flags diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway index 2096f194..2096f194 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/gateway diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname index 5dc539d5..5dc539d5 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/hostname diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/index b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index index 0cfbf088..0cfbf088 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/index +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/index diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr index 61ef5585..61ef5585 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/ip-addr diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac index 2fc3d525..2fc3d525 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/mac +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/mac diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/origin +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/origin diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len index a45fd52c..a45fd52c 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/prefix-len diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns index 6fa8c742..6fa8c742 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/primary-dns diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns index a7269ff5..a7269ff5 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/secondary-dns diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask index d30f9e9f..d30f9e9f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/subnet-mask diff --git a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan +++ b/src/core/initrd/tests/sysfs/firmware/ibft/ethernet2/vlan diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/flags b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/flags +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/flags diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/index b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/index index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/index +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/index diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name index 337b5a0f..337b5a0f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/initiator-name diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server index 4aff9398..4aff9398 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/isns-server +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/isns-server diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server index a26fb649..a26fb649 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/pri-radius-server diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server index 908be27f..908be27f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/sec-radius-server diff --git a/src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server index fca9e24b..fca9e24b 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/initiator/slp-server +++ b/src/core/initrd/tests/sysfs/firmware/ibft/initiator/slp-server diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/chap-type b/src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/chap-type +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/chap-type diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/flags b/src/core/initrd/tests/sysfs/firmware/ibft/target0/flags index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/flags +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/flags diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/index b/src/core/initrd/tests/sysfs/firmware/ibft/target0/index index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/index +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/index diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr index 994b6e9c..994b6e9c 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/ip-addr +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/ip-addr diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/lun b/src/core/initrd/tests/sysfs/firmware/ibft/target0/lun index 7c295bd4..7c295bd4 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/lun +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/lun diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc b/src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/nic-assoc diff --git a/src/initrd/tests/sysfs/firmware/ibft/target0/port b/src/core/initrd/tests/sysfs/firmware/ibft/target0/port index 53f0295f..53f0295f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target0/port +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target0/port diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/chap-type b/src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type index 573541ac..573541ac 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/chap-type +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/chap-type diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/flags b/src/core/initrd/tests/sysfs/firmware/ibft/target2/flags index 00750edc..00750edc 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/flags +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/flags diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/index b/src/core/initrd/tests/sysfs/firmware/ibft/target2/index index 0cfbf088..0cfbf088 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/index +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/index diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr b/src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr index a210477e..a210477e 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/ip-addr +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/ip-addr diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/lun b/src/core/initrd/tests/sysfs/firmware/ibft/target2/lun index 7c295bd4..7c295bd4 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/lun +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/lun diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc b/src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc index 0cfbf088..0cfbf088 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/nic-assoc diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/port b/src/core/initrd/tests/sysfs/firmware/ibft/target2/port index 53f0295f..53f0295f 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/port +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/port diff --git a/src/initrd/tests/sysfs/firmware/ibft/target2/target-name b/src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name index f4094320..f4094320 100644 --- a/src/initrd/tests/sysfs/firmware/ibft/target2/target-name +++ b/src/core/initrd/tests/sysfs/firmware/ibft/target2/target-name diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/core/initrd/tests/test-cmdline-reader.c index 14a83c08..cb65cd33 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/core/initrd/tests/test-cmdline-reader.c @@ -1,14 +1,13 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> #include <unistd.h> -#include <netinet/ether.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> @@ -20,26 +19,75 @@ #include "nm-test-utils-core.h" +#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" + +/*****************************************************************************/ + +#define _parse(ARGV, out_hostname, out_carrier_timeout_sec) \ + ({ \ + const char *const *const _ARGV = (ARGV); \ + char **const _out_hostname = (out_hostname); \ + gint64 *const _out_carrier_timeout_sec = (out_carrier_timeout_sec); \ + GHashTable * _connections; \ + \ + _connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", \ + _ARGV, \ + _out_hostname, \ + _out_carrier_timeout_sec); \ + \ + g_assert(_connections); \ + \ + _connections; \ + }) + +#define _parse_cons(ARGV) \ + ({ \ + GHashTable * _con_connections; \ + gs_free char *_con_hostname = NULL; \ + gint64 _con_carrier_timeout_sec = 0; \ + \ + _con_connections = _parse((ARGV), \ + nmtst_get_rand_bool() ? &_con_hostname : NULL, \ + nmtst_get_rand_bool() ? &_con_carrier_timeout_sec : NULL); \ + g_assert_cmpstr(_con_hostname, ==, NULL); \ + g_assert_cmpint(_con_carrier_timeout_sec, ==, 0); \ + \ + _con_connections; \ + }) + +#define _parse_con(ARGV, connection_name) \ + ({ \ + gs_unref_hashtable GHashTable *_1_connections = NULL; \ + NMConnection * _1_connection; \ + const char *const _1_connection_name = (connection_name); \ + \ + g_assert(_1_connection_name); \ + \ + _1_connections = _parse_cons((ARGV)); \ + \ + g_assert_cmpint(g_hash_table_size(_1_connections), ==, 1); \ + \ + _1_connection = g_hash_table_lookup(_1_connections, _1_connection_name); \ + g_assert(NM_IS_CONNECTION(_1_connection)); \ + \ + nmtst_assert_connection_verifies_without_normalization(_1_connection); \ + \ + NM_CONNECTION(g_object_ref(_1_connection)); \ + }) + +/*****************************************************************************/ + static void test_auto(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=auto"); - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; - - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + const char *const *ARGV = NM_MAKE_STRV("ip=auto"); + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connection = g_hash_table_lookup(connections, "default_connection"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); + connection = _parse_con(ARGV, "default_connection"); g_assert(!nm_connection_get_setting_vlan(connection)); @@ -89,15 +137,16 @@ test_dhcp_with_hostname(void) NMSettingWired * s_wired; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 1); g_assert_cmpstr(hostname, ==, "host1"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "default_connection"); - g_assert(connection); + nmtst_assert_connection_verifies_without_normalization(connection); g_assert(!nm_connection_get_setting_vlan(connection)); @@ -139,22 +188,13 @@ test_dhcp_with_mtu(void) guint i; for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { - gs_unref_hashtable GHashTable *connections = NULL; - NMConnection * connection; - NMSettingConnection * s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; - - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connection = g_hash_table_lookup(connections, "default_connection"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); + connection = _parse_con(ARGV[i], "default_connection"); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -192,22 +232,14 @@ test_dhcp_with_mtu(void) static void test_if_auto_with_mtu(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=eth0:auto:1666"); - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("ip=eth0:auto:1666"); + gs_unref_object NMConnection *connection = NULL; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "eth0"); - connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); s_wired = nm_connection_get_setting_wired(connection); @@ -228,21 +260,13 @@ test_if_auto_with_mtu(void) static void test_if_dhcp6(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=eth1:dhcp6"); - NMConnection * connection; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("ip=eth1:dhcp6"); + gs_unref_object NMConnection *connection = NULL; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "eth1"); - connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); s_ip4 = nm_connection_get_setting_ip4_config(connection); @@ -261,22 +285,14 @@ test_if_dhcp6(void) static void test_if_auto_with_mtu_and_mac(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=eth2:auto6:2048:00:53:ef:12:34:56"); - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("ip=eth2:auto6:2048:00:53:ef:12:34:56"); + gs_unref_object NMConnection *connection = NULL; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "eth2"); - connection = g_hash_table_lookup(connections, "eth2"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth2"); s_wired = nm_connection_get_setting_wired(connection); @@ -310,15 +326,15 @@ test_if_ip4_manual(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMIPAddress * ip_addr; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 2); g_assert_cmpstr(hostname, ==, "hostname1.example.com"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "eth3"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth3"); @@ -351,7 +367,6 @@ test_if_ip4_manual(void) g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); connection = g_hash_table_lookup(connections, "eth4"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth4"); @@ -386,15 +401,15 @@ test_if_ip6_manual(void) NMConnection * connection; NMSettingIPConfig * s_ip6; NMIPAddress * ip_addr; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 1); g_assert_cmpstr(hostname, ==, "hostname0.example.com"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "eth4"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth4"); @@ -427,7 +442,6 @@ test_if_off(void) NMConnection * connection; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; struct { const char name[32]; const char ipv4_method[32]; @@ -442,14 +456,11 @@ test_if_off(void) {"ens5", NM_SETTING_IP4_CONFIG_METHOD_DISABLED, NM_SETTING_IP6_CONFIG_METHOD_MANUAL}, }; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, G_N_ELEMENTS(conn_expected)); - g_assert_cmpstr(hostname, ==, NULL); for (int i = 0; i < G_N_ELEMENTS(conn_expected); ++i) { connection = g_hash_table_lookup(connections, conn_expected[i].name); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_ip4 = nm_connection_get_setting_ip4_config(connection); @@ -472,15 +483,15 @@ test_if_mac_ifname(void) NMSettingIPConfig * s_ip6; NMSettingWired * s_wired; NMIPAddress * ip_addr; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 1); g_assert_cmpstr(hostname, ==, "hostname0"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "00:11:22:33:44:55"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "00:11:22:33:44:55"); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); @@ -510,25 +521,17 @@ test_if_mac_ifname(void) static void test_multiple_merge(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = + const char *const *ARGV = NM_MAKE_STRV("ip=192.0.2.2/16:::::eth0", "ip=[2001:db8::2]:::56::eth0"); - NMConnection * connection; - NMSettingConnection *s_con; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - NMIPAddress * ip_addr; - gs_free char * hostname = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingConnection * s_con; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; + NMIPAddress * ip_addr; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "eth0"); - connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); s_con = nm_connection_get_setting_connection(connection); @@ -567,18 +570,20 @@ static void test_multiple_bootdev(void) { gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = - NM_MAKE_STRV("nameserver=1.2.3.4", "ip=eth3:auto6", "ip=eth4:dhcp", "bootdev=eth4"); + + const char *const *ARGV = NM_MAKE_STRV("nameserver=1.2.3.4", + "ip=eth3:auto6", + "ip=eth4:dhcp", + "ip=eth5:link6", + "bootdev=eth4"); + NMConnection * connection; NMSettingConnection *s_con; NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); + connections = _parse_cons(ARGV); + g_assert_cmpint(g_hash_table_size(connections), ==, 3); connection = g_hash_table_lookup(connections, "eth3"); g_assert(connection); @@ -601,6 +606,17 @@ test_multiple_bootdev(void) g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); g_assert_cmpint(nm_setting_ip_config_get_num_dns(s_ip4), ==, 1); g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip4, 0), ==, "1.2.3.4"); + + connection = g_hash_table_lookup(connections, "eth5"); + g_assert(connection); + s_con = nm_connection_get_setting_connection(connection); + g_assert(s_con); + g_assert_cmpint(nm_setting_connection_get_wait_device_timeout(s_con), ==, -1); + s_ip6 = nm_connection_get_setting_ip6_config(connection); + g_assert(s_ip6); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), + ==, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL); } static void @@ -610,15 +626,11 @@ test_bootdev(void) const char *const * ARGV = NM_MAKE_STRV("vlan=vlan2:ens5", "bootdev=ens3"); NMConnection * connection; NMSettingConnection * s_con; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "ens3"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); @@ -633,7 +645,6 @@ test_bootdev(void) NMI_WAIT_DEVICE_TIMEOUT_MS); connection = g_hash_table_lookup(connections, "vlan2"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); @@ -645,7 +656,6 @@ test_bootdev(void) g_assert_cmpstr(nm_setting_connection_get_interface_name(s_con), ==, "vlan2"); connection = g_hash_table_lookup(connections, "ens5"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); @@ -676,15 +686,11 @@ test_some_more(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMIPRoute * ip_route; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); @@ -719,7 +725,6 @@ test_some_more(void) g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip6, 0), ==, "2001:db8:3::53"); connection = g_hash_table_lookup(connections, "ens10"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); @@ -766,15 +771,11 @@ test_bond(void) NMSettingBond * s_bond; NMIPRoute * ip_route; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "bong0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -812,7 +813,6 @@ test_bond(void) g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -829,7 +829,6 @@ test_bond(void) NM_CONNECTION_MULTI_CONNECT_SINGLE); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); @@ -862,15 +861,11 @@ test_bond_ip(void) NMSettingBond * s_bond; NMIPAddress * ip_addr; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "bond0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -915,7 +910,6 @@ test_bond_ip(void) g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -932,7 +926,6 @@ test_bond_ip(void) NM_CONNECTION_MULTI_CONNECT_SINGLE); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); @@ -960,16 +953,12 @@ test_bond_default(void) NMSettingIPConfig * s_ip6; NMSettingBond * s_bond; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "bond0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1000,7 +989,6 @@ test_bond_default(void) g_assert_cmpstr(nm_setting_bond_get_option_by_name(s_bond, "mode"), ==, "balance-rr"); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -1031,15 +1019,11 @@ test_bridge(void) NMSettingBridge * s_bridge; NMIPRoute * ip_route; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "bridge0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1077,7 +1061,6 @@ test_bridge(void) g_assert_cmpint(nm_setting_bridge_get_stp(s_bridge), ==, FALSE); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -1096,7 +1079,6 @@ test_bridge(void) NM_CONNECTION_MULTI_CONNECT_SINGLE); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); @@ -1126,16 +1108,12 @@ test_bridge_default(void) NMSettingIPConfig * s_ip6; NMSettingBridge * s_bridge; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "br0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1164,7 +1142,6 @@ test_bridge_default(void) g_assert(s_bridge); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -1197,16 +1174,12 @@ test_bridge_ip(void) NMSettingWired * s_wired; NMSettingBridge * s_bridge; const char * master_uuid; - gs_free char * hostname = NULL; guint i; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 11); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "bridge123"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1237,7 +1210,6 @@ test_bridge_ip(void) nm_sprintf_buf(ifname, "eth%u", i); connection = g_hash_table_lookup(connections, ifname); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, ifname); @@ -1268,15 +1240,11 @@ test_team(void) NMSettingIPConfig * s_ip6; NMSettingTeam * s_team; const char * master_uuid; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 3); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "team0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1307,7 +1275,6 @@ test_team(void) g_assert(s_team); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); @@ -1324,7 +1291,6 @@ test_team(void) NM_CONNECTION_MULTI_CONNECT_SINGLE); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth1"); @@ -1355,16 +1321,12 @@ test_vlan(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSettingVlan * s_vlan; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); - g_assert(connections); + connections = _parse_cons(ARGV[i]); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); /* VLAN eth0.100 */ connection = g_hash_table_lookup(connections, "eth0.100"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1390,7 +1352,6 @@ test_vlan(void) /* Ethernet eth0 */ connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1425,16 +1386,12 @@ test_vlan_with_dhcp_on_parent(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSettingVlan * s_vlan; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); - g_assert(connections); + connections = _parse_cons(ARGV[i]); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); /* VLAN eth0.100 */ connection = g_hash_table_lookup(connections, "eth0.100"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1460,7 +1417,6 @@ test_vlan_with_dhcp_on_parent(void) /* Ethernet eth0 */ connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1502,16 +1458,12 @@ test_vlan_over_bond(void) NMSettingIPConfig * s_ip4; NMSettingIPConfig * s_ip6; NMSettingVlan * s_vlan; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV[i], &hostname); - g_assert(connections); + connections = _parse_cons(ARGV[i]); g_assert_cmpint(g_hash_table_size(connections), ==, 4); - g_assert_cmpstr(hostname, ==, NULL); /* VLAN vlan1 */ connection = g_hash_table_lookup(connections, "vlan1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1537,7 +1489,6 @@ test_vlan_over_bond(void) /* Bond bond2 */ connection = g_hash_table_lookup(connections, "bond2"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, @@ -1567,19 +1518,11 @@ test_vlan_over_bond(void) static void test_ibft_ip_dev(void) { - const char *const *ARGV = NM_MAKE_STRV("ip=eth0:ibft"); - gs_unref_hashtable GHashTable *connections = NULL; - NMSettingConnection * s_con; - NMConnection * connection; - gs_free char * hostname = NULL; - - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + const char *const * ARGV = NM_MAKE_STRV("ip=eth0:ibft"); + NMSettingConnection *s_con; + gs_unref_object NMConnection *connection = NULL; - connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); + connection = _parse_con(ARGV, "eth0"); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1592,19 +1535,11 @@ test_ibft_ip_dev(void) static void test_ibft_ip_dev_mac(void) { - const char *const *ARGV = NM_MAKE_STRV("ip=00-53-06-66-ab-01:ibft"); - gs_unref_hashtable GHashTable *connections = NULL; - NMSettingConnection * s_con; - NMConnection * connection; - gs_free char * hostname = NULL; - - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + const char *const * ARGV = NM_MAKE_STRV("ip=00-53-06-66-ab-01:ibft"); + NMSettingConnection *s_con; + gs_unref_object NMConnection *connection = NULL; - connection = g_hash_table_lookup(connections, "00:53:06:66:AB:01"); - g_assert(connection); + connection = _parse_con(ARGV, "00:53:06:66:AB:01"); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1619,21 +1554,17 @@ _test_ibft_ip(const char *const *ARGV) { gs_unref_hashtable GHashTable *connections = NULL; NMConnection * connection; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "ibft0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "iBFT VLAN Connection 0"); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); connection = g_hash_table_lookup(connections, "ibft2"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "iBFT Connection 2"); g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); @@ -1660,12 +1591,9 @@ test_ignore_extra(void) { gs_unref_hashtable GHashTable *connections = NULL; const char *const * ARGV = NM_MAKE_STRV("blabla", "extra", "lalala"); - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_assert_cmpstr(hostname, ==, NULL); } static void @@ -1686,12 +1614,13 @@ test_rd_znet(void) {.name = "portno", .value_str = "1"}, }; int i_s390_options_keys; - gs_free char *hostname = NULL; + gs_free char *hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 2); g_assert_cmpstr(hostname, ==, "foo.example.com"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "enc800"); g_assert(NM_IS_CONNECTION(connection)); @@ -1772,12 +1701,13 @@ test_rd_znet_legacy(void) "net.ifnames=0"); NMConnection * connection; NMSettingConnection *s_con; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 2); g_assert_cmpstr(hostname, ==, "foo.example.com"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "eth0"); g_assert(NM_IS_CONNECTION(connection)); @@ -1812,33 +1742,22 @@ test_rd_znet_no_ip(void) gs_unref_hashtable GHashTable *connections = NULL; const char *const *const ARGV = NM_MAKE_STRV("rd.znet=qeth,0.0.0800,0.0.0801,0.0.0802,layer2=0,portno=1"); - gs_free char *hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_assert_cmpstr(hostname, ==, NULL); } static void test_bootif_ip(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03", "ip=dhcp"); - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03", "ip=dhcp"); + gs_unref_object NMConnection *connection = NULL; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "default_connection"); - connection = g_hash_table_lookup(connections, "default_connection"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); s_wired = nm_connection_get_setting_wired(connection); @@ -1867,15 +1786,11 @@ test_neednet(void) "bridge=br0:eno3"); NMConnection * connection; NMSettingConnection * s_con; - gs_free char * hostname = NULL; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 4); - g_assert_cmpstr(hostname, ==, NULL); connection = g_hash_table_lookup(connections, "eno1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1885,7 +1800,6 @@ test_neednet(void) NMI_WAIT_DEVICE_TIMEOUT_MS); connection = g_hash_table_lookup(connections, "eno2"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1895,7 +1809,6 @@ test_neednet(void) NMI_WAIT_DEVICE_TIMEOUT_MS); connection = g_hash_table_lookup(connections, "eno3"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1905,7 +1818,6 @@ test_neednet(void) NMI_WAIT_DEVICE_TIMEOUT_MS); connection = g_hash_table_lookup(connections, "br0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_con = nm_connection_get_setting_connection(connection); g_assert(s_con); @@ -1916,22 +1828,14 @@ test_neednet(void) static void test_bootif_no_ip(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03"); - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig * s_ip4; - NMSettingIPConfig * s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("BOOTIF=00:53:AB:cd:02:03"); + gs_unref_object NMConnection *connection = NULL; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "default_connection"); - connection = g_hash_table_lookup(connections, "default_connection"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_id(connection), ==, "Wired Connection"); s_wired = nm_connection_get_setting_wired(connection); @@ -1952,59 +1856,68 @@ test_bootif_no_ip(void) static void test_bootif_hwtype(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const *ARGV = NM_MAKE_STRV("ip=eth0:dhcp", "BOOTIF=01-00-53-AB-cd-02-03"); - NMConnection * connection; - NMSettingWired * s_wired; - NMSettingIPConfig *s_ip4; - NMSettingIPConfig *s_ip6; - gs_free char * hostname = NULL; + const char *const *ARGV0 = NM_MAKE_STRV("ip=eth0:dhcp", "BOOTIF=01-00-53-AB-cd-02-03"); + const char *const *ARGV1 = NM_MAKE_STRV("ip=eth0:dhcp", "BOOTIF=00-00-53-Ab-cD-02-03"); + const char *const *ARGV[] = {ARGV0, ARGV1}; + guint i; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 2); - g_assert_cmpstr(hostname, ==, NULL); + for (i = 0; i < G_N_ELEMENTS(ARGV); i++) { + gs_unref_hashtable GHashTable *connections = NULL; + NMConnection * connection; + NMSettingWired * s_wired; + NMSettingIPConfig * s_ip4; + NMSettingIPConfig * s_ip6; - connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); + connections = _parse_cons(ARGV[i]); + g_assert_cmpint(g_hash_table_size(connections), ==, 2); - s_wired = nm_connection_get_setting_wired(connection); - g_assert(!nm_setting_wired_get_mac_address(s_wired)); - g_assert(s_wired); + connection = g_hash_table_lookup(connections, "eth0"); + nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "eth0"); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert(!nm_setting_ip_config_get_may_fail(s_ip4)); + s_wired = nm_connection_get_setting_wired(connection); + g_assert(!nm_setting_wired_get_mac_address(s_wired)); + g_assert(s_wired); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); + s_ip4 = nm_connection_get_setting_ip4_config(connection); + g_assert(s_ip4); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); + g_assert(!nm_setting_ip_config_get_may_fail(s_ip4)); - connection = g_hash_table_lookup(connections, "bootif_connection"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - g_assert_cmpstr(nm_connection_get_id(connection), ==, "BOOTIF Connection"); + s_ip6 = nm_connection_get_setting_ip6_config(connection); + g_assert(s_ip6); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), + ==, + NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - s_wired = nm_connection_get_setting_wired(connection); - g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:53:AB:CD:02:03"); - g_assert(s_wired); + connection = g_hash_table_lookup(connections, "bootif_connection"); + nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_id(connection), ==, "BOOTIF Connection"); - s_ip4 = nm_connection_get_setting_ip4_config(connection); - g_assert(s_ip4); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); - g_assert(nm_setting_ip_config_get_may_fail(s_ip4)); + s_wired = nm_connection_get_setting_wired(connection); + g_assert_cmpstr(nm_setting_wired_get_mac_address(s_wired), ==, "00:53:AB:CD:02:03"); + g_assert(s_wired); - s_ip6 = nm_connection_get_setting_ip6_config(connection); - g_assert(s_ip6); - g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_AUTO); - g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); - g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); + s_ip4 = nm_connection_get_setting_ip4_config(connection); + g_assert(s_ip4); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip4), + ==, + NM_SETTING_IP4_CONFIG_METHOD_AUTO); + g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip4)); + g_assert(nm_setting_ip_config_get_may_fail(s_ip4)); + + s_ip6 = nm_connection_get_setting_ip6_config(connection); + g_assert(s_ip6); + g_assert_cmpstr(nm_setting_ip_config_get_method(s_ip6), + ==, + NM_SETTING_IP6_CONFIG_METHOD_AUTO); + g_assert(!nm_setting_ip_config_get_ignore_auto_dns(s_ip6)); + g_assert(nm_setting_ip_config_get_may_fail(s_ip6)); + } } /* Check that nameservers are assigned to all existing @@ -2024,15 +1937,15 @@ test_nameserver(void) "nameserver=[2606:4700:4700::1111]"); NMConnection * connection; NMSettingIPConfig *s_ip; - gs_free char * hostname = NULL; + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); g_assert_cmpint(g_hash_table_size(connections), ==, 3); g_assert_cmpstr(hostname, ==, "foo.example.com"); + g_assert_cmpint(carrier_timeout_sec, ==, 0); connection = g_hash_table_lookup(connections, "eth0"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_ip = nm_connection_get_setting_ip4_config(connection); @@ -2042,7 +1955,6 @@ test_nameserver(void) g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 1), ==, "1.0.0.1"); connection = g_hash_table_lookup(connections, "eth1"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_ip = nm_connection_get_setting_ip6_config(connection); @@ -2051,7 +1963,6 @@ test_nameserver(void) g_assert_cmpstr(nm_setting_ip_config_get_dns(s_ip, 0), ==, "2606:4700:4700::1111"); connection = g_hash_table_lookup(connections, "eth2"); - g_assert(connection); nmtst_assert_connection_verifies_without_normalization(connection); s_ip = nm_connection_get_setting_ip4_config(connection); @@ -2065,77 +1976,52 @@ static void test_bootif_off(void) { gs_unref_hashtable GHashTable *connections = NULL; - const char *const *ARGV = NM_MAKE_STRV("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0"); - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("BOOTIF=01-00-53-AB-cd-02-03", "rd.bootif=0"); - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); + connections = _parse_cons(ARGV); g_assert_cmpint(g_hash_table_size(connections), ==, 0); - g_assert_cmpstr(hostname, ==, NULL); } static void test_dhcp_vendor_class_id(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class=testvci", "ip=eno1:dhcp"); - NMConnection * connection; - NMSettingIP4Config *s_ip4; - gs_free char * hostname = NULL; - gs_free char * vci_long = NULL; - char vci_arg_long[512] = {0}; - - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); - - connection = g_hash_table_lookup(connections, "eno1"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); + const char *const *ARGV; + gs_unref_object NMConnection *connection = NULL; + NMSettingIP4Config * s_ip4; + gs_free char * vci_long = NULL; + char vci_arg_long[512] = {0}; + + ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class=testvci", "ip=eno1:dhcp"); + connection = _parse_con(ARGV, "eno1"); + s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); g_assert_cmpstr(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4), ==, "testvci"); - nm_clear_pointer(&connections, g_hash_table_unref); + g_clear_object(&connection); - ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class", "ip=eno1:dhcp"); - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - connection = g_hash_table_lookup(connections, "eno1"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); + ARGV = NM_MAKE_STRV("rd.net.dhcp.vendor-class", "ip=eno1:dhcp"); + connection = _parse_con(ARGV, "eno1"); + s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); g_assert(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4) == NULL); - nm_clear_pointer(&connections, g_hash_table_unref); + g_clear_object(&connection); memset(vci_arg_long, 'A', 400); - vci_long = g_strdup_printf("rd.net.dhcp.vendor-class=%s", vci_arg_long); - ARGV = NM_MAKE_STRV(vci_long, "ip=eno1:dhcp"); - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - connection = g_hash_table_lookup(connections, "eno1"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); - s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); + vci_long = g_strdup_printf("rd.net.dhcp.vendor-class=%s", vci_arg_long); + ARGV = NM_MAKE_STRV(vci_long, "ip=eno1:dhcp"); + connection = _parse_con(ARGV, "eno1"); + s_ip4 = NM_SETTING_IP4_CONFIG(nm_connection_get_setting_ip4_config(connection)); g_assert(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4) == NULL); } static void test_infiniband_iface(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = NM_MAKE_STRV("ip=ib1:dhcp"); - NMConnection * connection; - NMSettingInfiniband * s_ib; - gs_free char * hostname = NULL; + const char *const *ARGV = NM_MAKE_STRV("ip=ib1:dhcp"); + gs_unref_object NMConnection *connection = NULL; + NMSettingInfiniband * s_ib; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "ib1"); - connection = g_hash_table_lookup(connections, "ib1"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, NM_SETTING_INFINIBAND_SETTING_NAME); @@ -2146,22 +2032,13 @@ test_infiniband_iface(void) static void test_infiniband_mac(void) { - gs_unref_hashtable GHashTable *connections = NULL; - const char *const * ARGV = + const char *const *ARGV = NM_MAKE_STRV("ip=00-11-22-33-44-55-66-77-88-99-aa-bb-cc-dd-ee-ff-00-11-22-33:dhcp"); - NMConnection * connection; - NMSettingInfiniband *s_ib; - gs_free char * hostname = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingInfiniband * s_ib; - connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); - g_assert(connections); - g_assert_cmpint(g_hash_table_size(connections), ==, 1); - g_assert_cmpstr(hostname, ==, NULL); + connection = _parse_con(ARGV, "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); - connection = g_hash_table_lookup(connections, - "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); - g_assert(connection); - nmtst_assert_connection_verifies_without_normalization(connection); g_assert_cmpstr(nm_connection_get_connection_type(connection), ==, NM_SETTING_INFINIBAND_SETTING_NAME); @@ -2173,6 +2050,20 @@ test_infiniband_mac(void) "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); } +static void +test_carrier_timeout(void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const * ARGV = NM_MAKE_STRV("rd.net.timeout.carrier=20"); + gs_free char * hostname = NULL; + gint64 carrier_timeout_sec = 0; + + connections = _parse(ARGV, &hostname, &carrier_timeout_sec); + g_assert_cmpint(g_hash_table_size(connections), ==, 0); + g_assert_cmpstr(hostname, ==, NULL); + g_assert_cmpint(carrier_timeout_sec, ==, 20); +} + NMTST_DEFINE(); int @@ -2221,6 +2112,7 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/dhcp/vendor_class_id", test_dhcp_vendor_class_id); g_test_add_func("/initrd/cmdline/infiniband/iface", test_infiniband_iface); g_test_add_func("/initrd/cmdline/infiniband/mac", test_infiniband_mac); + g_test_add_func("/initrd/cmdline/carrier_timeout", test_carrier_timeout); return g_test_run(); } diff --git a/src/initrd/tests/test-dt-reader.c b/src/core/initrd/tests/test-dt-reader.c index 0d457782..619a4e6f 100644 --- a/src/initrd/tests/test-dt-reader.c +++ b/src/core/initrd/tests/test-dt-reader.c @@ -1,14 +1,13 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> #include <unistd.h> -#include <netinet/ether.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> @@ -20,6 +19,10 @@ #include "nm-test-utils-core.h" +#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" + +/*****************************************************************************/ + static void test_read_dt_ofw(void) { diff --git a/src/initrd/tests/test-ibft-reader.c b/src/core/initrd/tests/test-ibft-reader.c index 51942b18..1d263b9e 100644 --- a/src/initrd/tests/test-ibft-reader.c +++ b/src/core/initrd/tests/test-ibft-reader.c @@ -1,14 +1,13 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> #include <unistd.h> -#include <netinet/ether.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> @@ -20,6 +19,10 @@ #include "nm-test-utils-core.h" +#define TEST_INITRD_DIR NM_BUILD_SRCDIR "/src/core/initrd/tests" + +/*****************************************************************************/ + static NMConnection * read_connection(const char *sysfs_dir, const char *expected_mac, GError **error) { diff --git a/src/main-utils.c b/src/core/main-utils.c index 3bc28014..9bc497ca 100644 --- a/src/main-utils.c +++ b/src/core/main-utils.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <fcntl.h> diff --git a/src/main-utils.h b/src/core/main-utils.h index 0cd4ee47..2eb731a1 100644 --- a/src/main-utils.h +++ b/src/core/main-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/main.c b/src/core/main.c index 467a1bed..9b79bcbb 100644 --- a/src/main.c +++ b/src/core/main.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2017 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <getopt.h> #include <locale.h> @@ -426,8 +426,9 @@ main(int argc, char *argv[]) } nm_log_info(LOGD_CORE, - "NetworkManager (version " NM_DIST_VERSION ") is starting... (%s)", - nm_config_get_first_start(config) ? "for the first time" : "after a restart"); + "NetworkManager (version " NM_DIST_VERSION ") is starting... (%s%s)", + nm_config_get_first_start(config) ? "for the first time" : "after a restart", + NM_MORE_ASSERTS != 0 ? ", asserts:" G_STRINGIFY(NM_MORE_ASSERTS) : ""); nm_log_info(LOGD_CORE, "Read config: %s", diff --git a/src/core/meson.build b/src/core/meson.build new file mode 100644 index 00000000..368a3e85 --- /dev/null +++ b/src/core/meson.build @@ -0,0 +1,333 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +src_inc = include_directories('.') + +core_plugin_dep = declare_dependency( + sources: libnm_core_enum_sources[1], + include_directories: [ + src_inc, + top_inc, + shared_inc, + libnm_core_inc, + ], + dependencies: [ + glib_dep, + ], +) + +core_default_dep = declare_dependency( + sources: libnm_core_enum_sources[1], + include_directories: src_inc, + dependencies: [ + libnm_core_nm_default_dep, + libnm_log_core_dep, + libnm_platform_dep, + ], +) + +install_data( + 'org.freedesktop.NetworkManager.conf', + install_dir: dbus_conf_dir, +) + +subdir('systemd') + +core_plugins = [] + +daemon_c_flags = [ + '-DG_LOG_DOMAIN="NetworkManager"', +] + +platform_wifi_wext_source = files() +if enable_wext + platform_wifi_wext_source += files('platform/wifi/nm-wifi-utils-wext.c') +endif + +libNetworkManagerBase = static_library( + 'NetworkManagerBase', + sources: files( + 'dhcp/nm-dhcp-client.c', + 'dhcp/nm-dhcp-manager.c', + 'dhcp/nm-dhcp-nettools.c', + 'dhcp/nm-dhcp-systemd.c', + 'dhcp/nm-dhcp-utils.c', + 'dhcp/nm-dhcp-options.c', + 'ndisc/nm-lndp-ndisc.c', + 'ndisc/nm-ndisc.c', + 'platform/wifi/nm-wifi-utils-nl80211.c', + 'platform/wifi/nm-wifi-utils.c', + 'platform/wpan/nm-wpan-utils.c', + 'platform/nm-linux-platform.c', + 'platform/nm-platform.c', + 'platform/nmp-object.c', + 'platform/nmp-rules-manager.c', + 'main-utils.c', + 'NetworkManagerUtils.c', + 'nm-core-utils.c', + 'nm-dbus-object.c', + 'nm-dbus-utils.c', + 'nm-netns.c', + 'nm-l3-config-data.c', + 'nm-l3-ipv4ll.c', + 'nm-l3cfg.c', + 'nm-ip-config.c', + 'nm-ip4-config.c', + 'nm-ip6-config.c', + ) + platform_wifi_wext_source, + dependencies: [ + core_default_dep, + libn_dhcp4_dep, + libnm_core_dep, + libnm_systemd_shared_dep, + libnm_udev_aux_dep, + libsystemd_dep, + libudev_dep, + ], + c_args: daemon_c_flags, +) + +nm_deps = [ + core_default_dep, + dl_dep, + libn_acd_dep, + libndp_dep, + libudev_dep, + logind_dep, +] + +if enable_concheck + nm_deps += libcurl_dep +endif + +if enable_libaudit + nm_deps += libaudit_dep +endif + +if enable_libpsl + nm_deps += libpsl_dep +endif + +if enable_selinux + nm_deps += selinux_dep +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', + 'devices/nm-device.c', + 'devices/nm-device-dummy.c', + 'devices/nm-device-ethernet.c', + 'devices/nm-device-ethernet-utils.c', + 'devices/nm-device-factory.c', + 'devices/nm-device-generic.c', + 'devices/nm-device-infiniband.c', + 'devices/nm-device-ip-tunnel.c', + 'devices/nm-device-macsec.c', + 'devices/nm-device-macvlan.c', + 'devices/nm-device-ppp.c', + 'devices/nm-device-tun.c', + 'devices/nm-device-veth.c', + 'devices/nm-device-vlan.c', + 'devices/nm-device-vrf.c', + 'devices/nm-device-vxlan.c', + 'devices/nm-device-wireguard.c', + 'devices/nm-device-wpan.c', + 'devices/nm-lldp-listener.c', + 'dhcp/nm-dhcp-dhclient.c', + 'dhcp/nm-dhcp-dhclient-utils.c', + 'dhcp/nm-dhcp-dhcpcanon.c', + 'dhcp/nm-dhcp-dhcpcd.c', + 'dhcp/nm-dhcp-listener.c', + 'dns/nm-dns-dnsmasq.c', + 'dns/nm-dns-manager.c', + 'dns/nm-dns-plugin.c', + 'dns/nm-dns-systemd-resolved.c', + 'dns/nm-dns-unbound.c', + 'dnsmasq/nm-dnsmasq-manager.c', + 'dnsmasq/nm-dnsmasq-utils.c', + 'ppp/nm-ppp-manager-call.c', + 'settings/plugins/keyfile/nms-keyfile-storage.c', + 'settings/plugins/keyfile/nms-keyfile-plugin.c', + 'settings/plugins/keyfile/nms-keyfile-reader.c', + 'settings/plugins/keyfile/nms-keyfile-utils.c', + 'settings/plugins/keyfile/nms-keyfile-writer.c', + 'settings/nm-agent-manager.c', + 'settings/nm-secret-agent.c', + 'settings/nm-settings.c', + 'settings/nm-settings-connection.c', + 'settings/nm-settings-plugin.c', + 'settings/nm-settings-storage.c', + 'settings/nm-settings-utils.c', + 'supplicant/nm-supplicant-config.c', + 'supplicant/nm-supplicant-interface.c', + 'supplicant/nm-supplicant-manager.c', + 'supplicant/nm-supplicant-settings-verify.c', + 'vpn/nm-vpn-connection.c', + 'vpn/nm-vpn-manager.c', + 'nm-active-connection.c', + 'nm-act-request.c', + 'nm-audit-manager.c', + 'nm-auth-manager.c', + 'nm-auth-utils.c', + 'nm-dbus-manager.c', + 'nm-checkpoint.c', + 'nm-checkpoint-manager.c', + 'nm-config.c', + 'nm-config-data.c', + 'nm-connectivity.c', + 'nm-dcb.c', + 'nm-dhcp-config.c', + 'nm-dispatcher.c', + 'nm-firewall-manager.c', + 'nm-hostname-manager.c', + 'nm-keep-alive.c', + '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', + ), + dependencies: nm_deps, + c_args: daemon_c_flags, + link_with: [ + libNetworkManagerBase, + libnm_systemd_core, + libnm_systemd_shared, + ], +) + +executable( + 'nm-iface-helper', + 'nm-iface-helper.c', + dependencies: [ + core_default_dep, + dl_dep, + libndp_dep, + libudev_dep, + libn_acd_dep, + ], + c_args: daemon_c_flags, + link_with: [ + libNetworkManagerBase, + libnm_systemd_core, + libnm_systemd_shared, + ], + link_args: ldflags_linker_script_binary, + link_depends: linker_script_binary, + install: true, + install_dir: nm_libexecdir, +) + +if enable_tests + test_c_flags = daemon_c_flags + if require_root_tests + test_c_flags += ['-DREQUIRE_ROOT_TESTS=1'] + endif + + libNetworkManagerTest = static_library( + 'NetworkManagerTest', + sources: files( + 'ndisc/nm-fake-ndisc.c', + 'platform/tests/test-common.c', + 'platform/nm-fake-platform.c', + ), + dependencies: core_default_dep, + c_args: test_c_flags, + link_with: libNetworkManager, + ) + + libNetworkManagerTest_dep = declare_dependency( + dependencies: core_default_dep, + link_with: libNetworkManagerTest, + ) + + subdir('dnsmasq/tests') + subdir('ndisc/tests') + subdir('platform/tests') + subdir('supplicant/tests') + subdir('tests') +endif + +subdir('dhcp') + +if enable_ppp + subdir('ppp') +endif + +subdir('devices') +subdir('initrd') +subdir('settings/plugins') + +# NetworkManager binary + +# libNetworkManager.a, as built by meson doesn't contain all symbols +# from libNetworkManagerBase.a and other static libraries, unless we +# add dependencies with link_whole, only supported in meson >= 0.46. +# Create an executable with full symbols that we use in place of the +# library to enumerate the symbols. +NetworkManager_all_sym = executable( + 'NetworkManager-all-sym', + 'main.c', + dependencies: nm_deps, + c_args: daemon_c_flags, + link_args: '-Wl,--no-gc-sections', + link_whole: [ + libNetworkManager, + libNetworkManagerBase, + libnm_core, + ], +) + +ver_script = custom_target( + 'NetworkManager.ver', + output: 'NetworkManager.ver', + depends: [ + NetworkManager_all_sym, + core_plugins, + ], + command: [ + join_paths(source_root, 'tools', 'create-exports-NetworkManager.sh'), + '--called-from-build', + source_root, + ], +) + +NetworkManager = executable( + 'NetworkManager', + 'main.c', + dependencies: nm_deps, + c_args: daemon_c_flags, + link_with: libNetworkManager, + link_args: [ + '-rdynamic', + '-Wl,--version-script,@0@'.format(ver_script.full_path()), + ], + link_depends: ver_script, + install: true, + install_dir: nm_sbindir, +) + +if enable_tests + foreach plugin: core_plugins + plugin_path = plugin.full_path() + + test( + 'sym/' + plugin_path.split('/')[-1], + NetworkManager, + args: '--version', + env: ['LD_BIND_NOW=1', 'LD_PRELOAD=' + plugin_path], + ) + endforeach +endif + +test( + 'check-config-options', + find_program(join_paths(source_root, 'tools', 'check-config-options.sh')), + args: source_root, +) diff --git a/src/ndisc/nm-fake-ndisc.c b/src/core/ndisc/nm-fake-ndisc.c index bd9f5f7e..ffe07ab6 100644 --- a/src/ndisc/nm-fake-ndisc.c +++ b/src/core/ndisc/nm-fake-ndisc.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-fake-ndisc.h" @@ -30,11 +30,10 @@ typedef struct { typedef struct { struct in6_addr network; - int plen; struct in6_addr gateway; - guint32 timestamp; - guint32 lifetime; - guint32 preferred; + gint64 expiry_msec; + gint64 expiry_preferred_msec; + int plen; NMIcmpv6RouterPref preference; } FakePrefix; @@ -128,8 +127,7 @@ void nm_fake_ndisc_add_gateway(NMFakeNDisc * self, guint ra_id, const char * addr, - guint32 timestamp, - guint32 lifetime, + gint64 expiry_msec, NMIcmpv6RouterPref preference) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); @@ -137,12 +135,12 @@ nm_fake_ndisc_add_gateway(NMFakeNDisc * self, NMNDiscGateway * gw; g_assert(ra); - g_array_set_size(ra->gateways, ra->gateways->len + 1); - gw = &g_array_index(ra->gateways, NMNDiscGateway, ra->gateways->len - 1); - g_assert(inet_pton(AF_INET6, addr, &gw->address) == 1); - gw->timestamp = timestamp; - gw->lifetime = lifetime; - gw->preference = preference; + + gw = nm_g_array_append_new(ra->gateways, NMNDiscGateway); + if (inet_pton(AF_INET6, addr, &gw->address) != 1) + g_assert_not_reached(); + gw->expiry_msec = expiry_msec; + gw->preference = preference; } void @@ -151,9 +149,8 @@ nm_fake_ndisc_add_prefix(NMFakeNDisc * self, const char * network, guint plen, const char * gateway, - guint32 timestamp, - guint32 lifetime, - guint32 preferred, + gint64 expiry_msec, + gint64 expiry_preferred_msec, NMIcmpv6RouterPref preference) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); @@ -161,54 +158,52 @@ nm_fake_ndisc_add_prefix(NMFakeNDisc * self, FakePrefix * prefix; g_assert(ra); - g_array_set_size(ra->prefixes, ra->prefixes->len + 1); - prefix = &g_array_index(ra->prefixes, FakePrefix, ra->prefixes->len - 1); - memset(prefix, 0, sizeof(*prefix)); - g_assert(inet_pton(AF_INET6, network, &prefix->network) == 1); - g_assert(inet_pton(AF_INET6, gateway, &prefix->gateway) == 1); - prefix->plen = plen; - prefix->timestamp = timestamp; - prefix->lifetime = lifetime; - prefix->preferred = preferred; - prefix->preference = preference; + + prefix = nm_g_array_append_new(ra->prefixes, FakePrefix); + *prefix = (FakePrefix){ + .plen = plen, + .expiry_msec = expiry_msec, + .expiry_preferred_msec = expiry_preferred_msec, + .preference = preference, + }; + if (inet_pton(AF_INET6, network, &prefix->network) != 1) + g_assert_not_reached(); + if (inet_pton(AF_INET6, gateway, &prefix->gateway) != 1) + g_assert_not_reached(); } void nm_fake_ndisc_add_dns_server(NMFakeNDisc *self, guint ra_id, const char * address, - guint32 timestamp, - guint32 lifetime) + gint64 expiry_msec) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); FakeRa * ra = find_ra(priv->ras, ra_id); NMNDiscDNSServer * dns; g_assert(ra); - g_array_set_size(ra->dns_servers, ra->dns_servers->len + 1); - dns = &g_array_index(ra->dns_servers, NMNDiscDNSServer, ra->dns_servers->len - 1); - g_assert(inet_pton(AF_INET6, address, &dns->address) == 1); - dns->timestamp = timestamp; - dns->lifetime = lifetime; + + dns = nm_g_array_append_new(ra->dns_servers, NMNDiscDNSServer); + + dns->expiry_msec = expiry_msec; + if (inet_pton(AF_INET6, address, &dns->address) != 1) + g_assert_not_reached(); } void -nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, - guint ra_id, - const char * domain, - guint32 timestamp, - guint32 lifetime) +nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, guint ra_id, const char *domain, gint64 expiry_msec) { NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE(self); FakeRa * ra = find_ra(priv->ras, ra_id); NMNDiscDNSDomain * dns; g_assert(ra); - g_array_set_size(ra->dns_domains, ra->dns_domains->len + 1); - dns = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, ra->dns_domains->len - 1); - dns->domain = g_strdup(domain); - dns->timestamp = timestamp; - dns->lifetime = lifetime; + + dns = nm_g_array_append_new(ra->dns_domains, NMNDiscDNSDomain); + + dns->domain = g_strdup(domain); + dns->expiry_msec = expiry_msec; } gboolean @@ -222,6 +217,7 @@ nm_fake_ndisc_done(NMFakeNDisc *self) static gboolean send_rs(NMNDisc *ndisc, GError **error) { + _LOGT("send_rs()"); g_signal_emit(ndisc, signals[RS_SENT], 0); return TRUE; } @@ -229,13 +225,13 @@ send_rs(NMNDisc *ndisc, GError **error) static gboolean receive_ra(gpointer user_data) { - NMFakeNDisc * self = user_data; - NMFakeNDiscPrivate * priv = NM_FAKE_NDISC_GET_PRIVATE(self); - NMNDisc * ndisc = NM_NDISC(self); - NMNDiscDataInternal *rdata = ndisc->rdata; - FakeRa * ra = priv->ras->data; - NMNDiscConfigMap changed = 0; - gint32 now = nm_utils_get_monotonic_timestamp_sec(); + NMFakeNDisc * self = user_data; + NMFakeNDiscPrivate * priv = NM_FAKE_NDISC_GET_PRIVATE(self); + NMNDisc * ndisc = NM_NDISC(self); + NMNDiscDataInternal *rdata = ndisc->rdata; + FakeRa * ra = priv->ras->data; + NMNDiscConfigMap changed = 0; + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); guint i; NMNDiscDHCPLevel dhcp_level; @@ -250,53 +246,51 @@ receive_ra(gpointer user_data) } for (i = 0; i < ra->gateways->len; i++) { - NMNDiscGateway *item = &g_array_index(ra->gateways, NMNDiscGateway, i); + const NMNDiscGateway *item = &g_array_index(ra->gateways, NMNDiscGateway, i); - if (nm_ndisc_add_gateway(ndisc, item)) + if (nm_ndisc_add_gateway(ndisc, item, now_msec)) changed |= NM_NDISC_CONFIG_GATEWAYS; } for (i = 0; i < ra->prefixes->len; i++) { - FakePrefix * item = &g_array_index(ra->prefixes, FakePrefix, i); - NMNDiscRoute route = { - .network = item->network, - .plen = item->plen, - .gateway = item->gateway, - .timestamp = item->timestamp, - .lifetime = item->lifetime, - .preference = item->preference, + FakePrefix * item = &g_array_index(ra->prefixes, FakePrefix, i); + const NMNDiscRoute route = { + .network = item->network, + .plen = item->plen, + .gateway = item->gateway, + .expiry_msec = item->expiry_msec, + .preference = item->preference, }; g_assert(route.plen > 0 && route.plen <= 128); - if (nm_ndisc_add_route(ndisc, &route)) + if (nm_ndisc_add_route(ndisc, &route, now_msec)) changed |= NM_NDISC_CONFIG_ROUTES; if (item->plen == 64) { - NMNDiscAddress address = { - .address = item->network, - .timestamp = item->timestamp, - .lifetime = item->lifetime, - .preferred = item->preferred, - .dad_counter = 0, + const NMNDiscAddress address = { + .address = item->network, + .expiry_msec = item->expiry_msec, + .expiry_preferred_msec = item->expiry_preferred_msec, + .dad_counter = 0, }; - if (nm_ndisc_complete_and_add_address(ndisc, &address, now)) + if (nm_ndisc_complete_and_add_address(ndisc, &address, now_msec)) changed |= NM_NDISC_CONFIG_ADDRESSES; } } for (i = 0; i < ra->dns_servers->len; i++) { - NMNDiscDNSServer *item = &g_array_index(ra->dns_servers, NMNDiscDNSServer, i); + const NMNDiscDNSServer *item = &g_array_index(ra->dns_servers, NMNDiscDNSServer, i); - if (nm_ndisc_add_dns_server(ndisc, item)) + if (nm_ndisc_add_dns_server(ndisc, item, now_msec)) changed |= NM_NDISC_CONFIG_DNS_SERVERS; } for (i = 0; i < ra->dns_domains->len; i++) { - NMNDiscDNSDomain *item = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, i); + const NMNDiscDNSDomain *item = &g_array_index(ra->dns_domains, NMNDiscDNSDomain, i); - if (nm_ndisc_add_dns_domain(ndisc, item)) + if (nm_ndisc_add_dns_domain(ndisc, item, now_msec)) changed |= NM_NDISC_CONFIG_DNS_DOMAINS; } @@ -313,7 +307,7 @@ receive_ra(gpointer user_data) priv->ras = g_slist_remove(priv->ras, priv->ras->data); fake_ra_free(ra); - nm_ndisc_ra_received(NM_NDISC(self), now, changed); + nm_ndisc_ra_received(NM_NDISC(self), now_msec, changed); /* Schedule next RA */ if (priv->ras) { @@ -378,7 +372,7 @@ nm_fake_ndisc_new(int ifindex, const char *ifname) NM_NDISC_ROUTER_SOLICITATIONS, NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT, NM_NDISC_ROUTER_SOLICITATION_INTERVAL, - NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT, + NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL, NM_NDISC_RA_TIMEOUT, 30u, NULL); diff --git a/src/ndisc/nm-fake-ndisc.h b/src/core/ndisc/nm-fake-ndisc.h index 47f40560..677f15fc 100644 --- a/src/ndisc/nm-fake-ndisc.h +++ b/src/core/ndisc/nm-fake-ndisc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ @@ -35,8 +35,7 @@ guint nm_fake_ndisc_add_ra(NMFakeNDisc * self, void nm_fake_ndisc_add_gateway(NMFakeNDisc * self, guint ra_id, const char * addr, - guint32 timestamp, - guint32 lifetime, + gint64 expiry_msec, NMIcmpv6RouterPref preference); void nm_fake_ndisc_add_prefix(NMFakeNDisc * self, @@ -44,22 +43,19 @@ void nm_fake_ndisc_add_prefix(NMFakeNDisc * self, const char * network, guint plen, const char * gateway, - guint32 timestamp, - guint32 lifetime, - guint32 preferred, + gint64 expiry_msec, + gint64 expiry_preferred_msec, NMIcmpv6RouterPref preference); void nm_fake_ndisc_add_dns_server(NMFakeNDisc *self, guint ra_id, const char * address, - guint32 timestamp, - guint32 lifetime); + gint64 expiry_msec); void nm_fake_ndisc_add_dns_domain(NMFakeNDisc *self, guint ra_id, const char * domain, - guint32 timestamp, - guint32 lifetime); + gint64 expiry_msec); void nm_fake_ndisc_emit_new_ras(NMFakeNDisc *self); diff --git a/src/ndisc/nm-lndp-ndisc.c b/src/core/ndisc/nm-lndp-ndisc.c index 22695c32..f773478f 100644 --- a/src/ndisc/nm-lndp-ndisc.c +++ b/src/core/ndisc/nm-lndp-ndisc.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-lndp-ndisc.h" @@ -13,10 +13,12 @@ #include <stdarg.h> #include <ndp.h> +#include "nm-glib-aux/nm-str-buf.h" +#include "systemd/nm-sd-utils-shared.h" #include "nm-ndisc-private.h" #include "NetworkManagerUtils.h" #include "platform/nm-platform.h" -#include "platform/nmp-netns.h" +#include "nm-platform/nmp-netns.h" #define _NMLOG_PREFIX_NAME "ndisc-lndp" @@ -83,14 +85,26 @@ send_rs(NMNDisc *ndisc, GError **error) static NMIcmpv6RouterPref _route_preference_coerce(enum ndp_route_preference pref) { +#define _ASSERT_ENUM(v1, v2) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT((NMIcmpv6RouterPref)(v1) == (v2)); \ + G_STATIC_ASSERT((enum ndp_route_preference)(v2) == (v1)); \ + G_STATIC_ASSERT((gint64)(v1) == (v2)); \ + G_STATIC_ASSERT((gint64)(v2) == (v1)); \ + } \ + G_STMT_END + switch (pref) { case NDP_ROUTE_PREF_LOW: - return NM_ICMPV6_ROUTER_PREF_LOW; case NDP_ROUTE_PREF_MEDIUM: - return NM_ICMPV6_ROUTER_PREF_MEDIUM; case NDP_ROUTE_PREF_HIGH: - return NM_ICMPV6_ROUTER_PREF_HIGH; + _ASSERT_ENUM(NDP_ROUTE_PREF_LOW, NM_ICMPV6_ROUTER_PREF_LOW); + _ASSERT_ENUM(NDP_ROUTE_PREF_MEDIUM, NM_ICMPV6_ROUTER_PREF_MEDIUM); + _ASSERT_ENUM(NDP_ROUTE_PREF_HIGH, NM_ICMPV6_ROUTER_PREF_HIGH); + return (NMIcmpv6RouterPref) pref; } + /* unexpected value must be treated as MEDIUM (RFC 4191). */ return NM_ICMPV6_ROUTER_PREF_MEDIUM; } @@ -103,7 +117,7 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) NMNDiscConfigMap changed = 0; struct ndp_msgra * msgra = ndp_msgra(msg); struct in6_addr gateway_addr; - gint32 now = nm_utils_get_monotonic_timestamp_sec(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); int offset; int hop_limit; guint32 val; @@ -119,7 +133,9 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) * single time when the configuration is finished and updates can * come at any time. */ - _LOGD("received router advertisement at %d", (int) now); + _LOGD("received router advertisement at timestamp %" G_GINT64_FORMAT ".%03d seconds", + now_msec / 1000, + (int) (now_msec % 1000)); gateway_addr = *ndp_msg_addrto(msg); if (IN6_IS_ADDR_UNSPECIFIED(&gateway_addr)) @@ -161,13 +177,18 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) */ { const NMNDiscGateway gateway = { - .address = gateway_addr, - .timestamp = now, - .lifetime = ndp_msgra_router_lifetime(msgra), - .preference = _route_preference_coerce(ndp_msgra_route_preference(msgra)), + .address = gateway_addr, + .expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msgra_router_lifetime(msgra)), + .preference = _route_preference_coerce(ndp_msgra_route_preference(msgra)), }; - if (nm_ndisc_add_gateway(ndisc, &gateway)) + /* https://tools.ietf.org/html/rfc2461#section-4.2 + * > A Lifetime of 0 indicates that the router is not a + * > default router and SHOULD NOT appear on the default + * > router list. + * We handle that by tracking a gateway that expires right now. */ + + if (nm_ndisc_add_gateway(ndisc, &gateway, now_msec)) changed |= NM_NDISC_CONFIG_GATEWAYS; } @@ -190,71 +211,71 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) if (ndp_msg_opt_prefix_flag_on_link(msg, offset)) { const NMNDiscRoute route = { - .network = r_network, - .plen = r_plen, - .timestamp = now, - .lifetime = ndp_msg_opt_prefix_valid_time(msg, offset), + .network = r_network, + .plen = r_plen, + .expiry_msec = + _nm_ndisc_lifetime_to_expiry(now_msec, + ndp_msg_opt_prefix_valid_time(msg, offset)), }; - if (nm_ndisc_add_route(ndisc, &route)) + if (nm_ndisc_add_route(ndisc, &route, now_msec)) changed |= NM_NDISC_CONFIG_ROUTES; } /* Address */ if (r_plen == 64 && ndp_msg_opt_prefix_flag_auto_addr_conf(msg, offset)) { - NMNDiscAddress address = { - .address = r_network, - .timestamp = now, - .lifetime = ndp_msg_opt_prefix_valid_time(msg, offset), - .preferred = ndp_msg_opt_prefix_preferred_time(msg, offset), + const guint32 valid_time = ndp_msg_opt_prefix_valid_time(msg, offset); + const guint32 preferred_time = + NM_MIN(ndp_msg_opt_prefix_preferred_time(msg, offset), valid_time); + const NMNDiscAddress address = { + .address = r_network, + .expiry_msec = _nm_ndisc_lifetime_to_expiry(now_msec, valid_time), + .expiry_preferred_msec = _nm_ndisc_lifetime_to_expiry(now_msec, preferred_time), }; - if (address.preferred <= address.lifetime) { - if (nm_ndisc_complete_and_add_address(ndisc, &address, now)) - changed |= NM_NDISC_CONFIG_ADDRESSES; - } + if (nm_ndisc_complete_and_add_address(ndisc, &address, now_msec)) + changed |= NM_NDISC_CONFIG_ADDRESSES; } } ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_ROUTE) { - NMNDiscRoute route = { - .gateway = gateway_addr, - .plen = ndp_msg_opt_route_prefix_len(msg, offset), - .timestamp = now, - .lifetime = ndp_msg_opt_route_lifetime(msg, offset), - .preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)), - }; + guint8 plen = ndp_msg_opt_route_prefix_len(msg, offset); + struct in6_addr network; - if (route.plen == 0 || route.plen > 128) + if (plen == 0 || plen > 128) continue; - /* Routers through this particular gateway */ - nm_utils_ip6_address_clear_host_address(&route.network, + nm_utils_ip6_address_clear_host_address(&network, ndp_msg_opt_route_prefix(msg, offset), - route.plen); - if (nm_ndisc_add_route(ndisc, &route)) - changed |= NM_NDISC_CONFIG_ROUTES; + plen); + + { + const NMNDiscRoute route = { + .network = network, + .gateway = gateway_addr, + .plen = plen, + .expiry_msec = + _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_route_lifetime(msg, offset)), + .preference = _route_preference_coerce(ndp_msg_opt_route_preference(msg, offset)), + }; + + /* Routers through this particular gateway */ + if (nm_ndisc_add_route(ndisc, &route, now_msec)) + changed |= NM_NDISC_CONFIG_ROUTES; + } } - /* DNS information */ ndp_msg_opt_for_each_offset (offset, msg, NDP_MSG_OPT_RDNSS) { struct in6_addr *addr; int addr_index; ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) { - NMNDiscDNSServer dns_server = { - .address = *addr, - .timestamp = now, - .lifetime = ndp_msg_opt_rdnss_lifetime(msg, offset), + const NMNDiscDNSServer dns_server = { + .address = *addr, + .expiry_msec = + _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_rdnss_lifetime(msg, offset)), }; - /* Pad the lifetime somewhat to give a bit of slack in cases - * where one RA gets lost or something (which can happen on unreliable - * links like Wi-Fi where certain types of frames are not retransmitted). - * Note that 0 has special meaning and is therefore not adjusted. - */ - if (dns_server.lifetime && dns_server.lifetime < 7200) - dns_server.lifetime = 7200; - if (nm_ndisc_add_dns_server(ndisc, &dns_server)) + if (nm_ndisc_add_dns_server(ndisc, &dns_server, now_msec)) changed |= NM_NDISC_CONFIG_DNS_SERVERS; } } @@ -263,20 +284,13 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) int domain_index; ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) { - NMNDiscDNSDomain dns_domain = { - .domain = domain, - .timestamp = now, - .lifetime = ndp_msg_opt_dnssl_lifetime(msg, offset), + const NMNDiscDNSDomain dns_domain = { + .domain = domain, + .expiry_msec = + _nm_ndisc_lifetime_to_expiry(now_msec, ndp_msg_opt_dnssl_lifetime(msg, offset)), }; - /* Pad the lifetime somewhat to give a bit of slack in cases - * where one RA gets lost or something (which can happen on unreliable - * links like Wi-Fi where certain types of frames are not retransmitted). - * Note that 0 has special meaning and is therefore not adjusted. - */ - if (dns_domain.lifetime && dns_domain.lifetime < 7200) - dns_domain.lifetime = 7200; - if (nm_ndisc_add_dns_domain(ndisc, &dns_domain)) + if (nm_ndisc_add_dns_domain(ndisc, &dns_domain, now_msec)) changed |= NM_NDISC_CONFIG_DNS_DOMAINS; } } @@ -316,50 +330,69 @@ receive_ra(struct ndp *ndp, struct ndp_msg *msg, gpointer user_data) } } - nm_ndisc_ra_received(ndisc, now, changed); + nm_ndisc_ra_received(ndisc, now_msec, changed); return 0; } static void * -_ndp_msg_add_option(struct ndp_msg *msg, int len) +_ndp_msg_add_option(struct ndp_msg *msg, gsize len) { - void *ret = (uint8_t *) msg + ndp_msg_payload_len(msg); + gsize payload_len = ndp_msg_payload_len(msg); + void *ret = &((uint8_t *) msg)[payload_len]; + + nm_assert(len <= G_MAXSIZE - payload_len); + len += payload_len; - len += ndp_msg_payload_len(msg); if (len > ndp_msg_payload_maxlen(msg)) return NULL; ndp_msg_payload_len_set(msg, len); + nm_assert(len == ndp_msg_payload_len(msg)); return ret; } +/*****************************************************************************/ + +/* "Recursive DNS Server Option" at https://tools.ietf.org/html/rfc8106#section-5.1 */ + #define NM_ND_OPT_RDNSS 25 -typedef struct { + +typedef struct _nm_packed { struct nd_opt_hdr header; uint16_t reserved; uint32_t lifetime; struct in6_addr addrs[0]; } NMLndpRdnssOption; +G_STATIC_ASSERT(sizeof(NMLndpRdnssOption) == 8u); + +/*****************************************************************************/ + +/* "DNS Search List Option" at https://tools.ietf.org/html/rfc8106#section-5.2 */ + #define NM_ND_OPT_DNSSL 31 -typedef struct { + +typedef struct _nm_packed { struct nd_opt_hdr header; uint16_t reserved; uint32_t lifetime; - char search_list[0]; + uint8_t search_list[0]; } NMLndpDnsslOption; +G_STATIC_ASSERT(sizeof(NMLndpDnsslOption) == 8u); + +/*****************************************************************************/ + static gboolean send_ra(NMNDisc *ndisc, GError **error) { - NMLndpNDiscPrivate * priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); - NMNDiscDataInternal * rdata = ndisc->rdata; - gint32 now = nm_utils_get_monotonic_timestamp_sec(); - int errsv; - struct in6_addr * addr; - struct ndp_msg * msg; - struct nd_opt_prefix_info *prefix; - int i; + NMLndpNDiscPrivate * priv = NM_LNDP_NDISC_GET_PRIVATE(ndisc); + NMNDiscDataInternal * rdata = ndisc->rdata; + int errsv; + struct in6_addr * addr; + struct ndp_msg * msg; + guint i; + nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE); errsv = ndp_msg_new(&msg, NDP_MSG_RA); if (errsv) { @@ -384,16 +417,8 @@ send_ra(NMNDisc *ndisc, GError **error) /* The device let us know about all addresses that the device got * whose prefixes are suitable for delegating. Let's announce them. */ for (i = 0; i < rdata->addresses->len; i++) { - NMNDiscAddress *address = &g_array_index(rdata->addresses, NMNDiscAddress, i); - guint32 age = NM_CLAMP((gint64) now - (gint64) address->timestamp, 0, G_MAXUINT32 - 1); - guint32 lifetime = address->lifetime; - guint32 preferred = address->preferred; - - /* Clamp the life times if they're not forever. */ - if (lifetime != NM_NDISC_INFINITY) - lifetime = lifetime > age ? lifetime - age : 0; - if (preferred != NM_NDISC_INFINITY) - preferred = preferred > age ? preferred - age : 0; + const NMNDiscAddress * address = &g_array_index(rdata->addresses, NMNDiscAddress, i); + struct nd_opt_prefix_info *prefix; prefix = _ndp_msg_add_option(msg, sizeof(*prefix)); if (!prefix) { @@ -407,67 +432,117 @@ send_ra(NMNDisc *ndisc, GError **error) prefix->nd_opt_pi_prefix_len = 64; prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK; prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO; - prefix->nd_opt_pi_valid_time = htonl(lifetime); - prefix->nd_opt_pi_preferred_time = htonl(preferred); + prefix->nd_opt_pi_valid_time = + htonl(_nm_ndisc_lifetime_from_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, + address->expiry_msec, + TRUE)); + prefix->nd_opt_pi_preferred_time = + htonl(_nm_ndisc_lifetime_from_expiry(NM_NDISC_EXPIRY_BASE_TIMESTAMP, + address->expiry_preferred_msec, + TRUE)); prefix->nd_opt_pi_prefix.s6_addr32[0] = address->address.s6_addr32[0]; prefix->nd_opt_pi_prefix.s6_addr32[1] = address->address.s6_addr32[1]; prefix->nd_opt_pi_prefix.s6_addr32[2] = 0; prefix->nd_opt_pi_prefix.s6_addr32[3] = 0; } - if (rdata->dns_servers->len) { + if (rdata->dns_servers->len > 0u) { NMLndpRdnssOption *option; - int len = sizeof(*option) + sizeof(option->addrs[0]) * rdata->dns_servers->len; + gsize len = sizeof(*option) + (sizeof(option->addrs[0]) * rdata->dns_servers->len); option = _ndp_msg_add_option(msg, len); - if (option) { - option->header.nd_opt_type = NM_ND_OPT_RDNSS; - option->header.nd_opt_len = len / 8; - option->lifetime = htonl(900); - - for (i = 0; i < rdata->dns_servers->len; i++) { - NMNDiscDNSServer *dns_server = - &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); - option->addrs[i] = dns_server->address; - } - } else { + if (!option) { _LOGW("The RA is too big, had to omit DNS information."); + goto dns_servers_done; + } + + option->header.nd_opt_type = NM_ND_OPT_RDNSS; + option->header.nd_opt_len = len / 8; + option->lifetime = htonl(900); + + for (i = 0; i < rdata->dns_servers->len; i++) { + const NMNDiscDNSServer *dns_server = + &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); + + option->addrs[i] = dns_server->address; } } +dns_servers_done: - if (rdata->dns_domains->len) { + if (rdata->dns_domains->len > 0u) { NMLndpDnsslOption *option; - NMNDiscDNSDomain * dns_server; - int len = sizeof(*option); - char * search_list; + gsize padding; + gsize len; + + nm_str_buf_reset(&sbuf); for (i = 0; i < rdata->dns_domains->len; i++) { - dns_server = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); - len += strlen(dns_server->domain) + 2; - } - len = (len + 8) & ~0x7; + const NMNDiscDNSDomain *dns_domain = + &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); + const char *domain = dns_domain->domain; + gsize domain_l; + gsize n_reserved; + int r; + + if (nm_str_is_empty(domain)) { + nm_assert_not_reached(); + continue; + } - option = _ndp_msg_add_option(msg, len); - if (option) { - option->header.nd_opt_type = NM_ND_OPT_DNSSL; - option->header.nd_opt_len = len / 8; - option->lifetime = htonl(900); - - search_list = option->search_list; - for (i = 0; i < rdata->dns_domains->len; i++) { - NMNDiscDNSDomain *dns_domain = - &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); - uint8_t domain_len = strlen(dns_domain->domain); - - *search_list++ = domain_len; - memcpy(search_list, dns_domain->domain, domain_len); - search_list += domain_len; - *search_list++ = '\0'; + domain_l = strlen(domain); + + nm_str_buf_maybe_expand(&sbuf, domain_l + 2u, FALSE); + n_reserved = sbuf.allocated - sbuf.len; + + r = nm_sd_dns_name_to_wire_format( + domain, + (guint8 *) (&nm_str_buf_get_str_unsafe(&sbuf)[sbuf.len]), + n_reserved, + FALSE); + + if (r < 0 || ((gsize) r) > n_reserved) { + nm_assert(r != -ENOBUFS); + nm_assert(r < 0); + /* we don't expect errors here, unless the domain name is invalid. + * That should have been caught (and rejected) by upper layers, but + * at this point it seems dangerous to assert (as it's hard to review + * that all callers got it correct). So instead silently ignore the error. */ + continue; } - } else { + + nm_str_buf_set_size(&sbuf, sbuf.len + ((gsize) r), TRUE, FALSE); + } + + if (sbuf.len == 0) { + /* no valid domains? */ + goto dns_domains_done; + } + + len = sizeof(*option) + sbuf.len; + padding = len % 8u; + if (padding != 0u) { + padding = 8u - padding; + len += padding; + } + + nm_assert(len % 8u == 0u); + nm_assert(len > 0u); + nm_assert(len / 8u >= 2u); + + if (len / 8u >= 256u || !(option = _ndp_msg_add_option(msg, len))) { _LOGW("The RA is too big, had to omit DNS search list."); + goto dns_domains_done; } + + nm_str_buf_append_c_len(&sbuf, '\0', padding); + + option->header.nd_opt_type = NM_ND_OPT_DNSSL; + option->header.nd_opt_len = len / 8u; + option->reserved = 0; + option->lifetime = htonl(900); + memcpy(option->search_list, nm_str_buf_get_str_unsafe(&sbuf), sbuf.len); } +dns_domains_done: errsv = ndp_msg_send(priv->ndp, msg); @@ -638,13 +713,12 @@ nm_lndp_ndisc_get_sysctl(NMPlatform *platform, NM_SET_OUT(out_router_solicitations, router_solicitations); } if (out_router_solicitation_interval || out_default_ra_timeout) { - router_solicitation_interval = - ipv6_sysctl_get(platform, - ifname, - "router_solicitation_interval", - 1, - G_MAXINT32, - NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT); + router_solicitation_interval = ipv6_sysctl_get(platform, + ifname, + "router_solicitation_interval", + 1, + G_MAXINT32, + NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL); NM_SET_OUT(out_router_solicitation_interval, router_solicitation_interval); } if (out_default_ra_timeout) { diff --git a/src/ndisc/nm-lndp-ndisc.h b/src/core/ndisc/nm-lndp-ndisc.h index a275be3e..96fc9737 100644 --- a/src/ndisc/nm-lndp-ndisc.h +++ b/src/core/ndisc/nm-lndp-ndisc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/ndisc/nm-ndisc-private.h b/src/core/ndisc/nm-ndisc-private.h index a79a920b..04739124 100644 --- a/src/ndisc/nm-ndisc-private.h +++ b/src/core/ndisc/nm-ndisc-private.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ @@ -21,14 +21,15 @@ struct _NMNDiscDataInternal { typedef struct _NMNDiscDataInternal NMNDiscDataInternal; -void nm_ndisc_ra_received(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed); +void nm_ndisc_ra_received(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed); void nm_ndisc_rs_received(NMNDisc *ndisc); -gboolean nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new); -gboolean nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s); -gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new); -gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new); -gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new); +gboolean nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new_item, gint64 now_msec); +gboolean +nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec); +gboolean nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec); +gboolean nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec); +gboolean nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec); /*****************************************************************************/ diff --git a/src/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c index f8805c02..a5c1b935 100644 --- a/src/ndisc/nm-ndisc.c +++ b/src/core/ndisc/nm-ndisc.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ndisc.h" @@ -15,43 +15,50 @@ #include "nm-ndisc-private.h" #include "nm-utils.h" #include "platform/nm-platform.h" -#include "platform/nmp-netns.h" +#include "nm-platform/nmp-netns.h" #include "nm-l3-config-data.h" #define _NMLOG_PREFIX_NAME "ndisc" +#define RFC7559_IRT ((gint32) 4) /* RFC7559, Initial Retransmission Time, in seconds */ +#define RFC7559_MRT ((gint32) 3600) /* RFC7559, Maximum Retransmission Time, in seconds */ + +#define _SIZE_MAX_GATEWAYS 100u +#define _SIZE_MAX_ADDRESSES 100u +#define _SIZE_MAX_ROUTES 1000u +#define _SIZE_MAX_DNS_SERVERS 64u +#define _SIZE_MAX_DNS_DOMAINS 64u + /*****************************************************************************/ struct _NMNDiscPrivate { /* this *must* be the first field. */ NMNDiscDataInternal rdata; - char * last_error; + char *last_error; + GSource *ra_timeout_source; - union { - gint32 solicitations_left; - gint32 announcements_left; - }; - union { - guint send_rs_id; - guint send_ra_id; - }; - union { - gint32 last_rs; - gint32 last_ra; - }; - guint timeout_id; /* prefix/dns/etc lifetime timeout */ + gint32 announcements_left; + guint send_ra_id; + gint32 last_ra; + + gint32 solicit_retransmit_time_msec; + + GSource *solicit_timer_source; + + GSource *timeout_expire_source; + NMUtilsIPv6IfaceId iid; /* immutable values: */ int ifindex; char * ifname; char * network_id; + guint max_addresses; NMSettingIP6ConfigAddrGenMode addr_gen_mode; NMUtilsStableType stable_type; guint32 ra_timeout; - gint32 max_addresses; gint32 router_solicitations; gint32 router_solicitation_interval; NMNDiscNodeType node_type; @@ -84,7 +91,8 @@ G_DEFINE_TYPE(NMNDisc, nm_ndisc, G_TYPE_OBJECT) /*****************************************************************************/ -static void _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed); +static void _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed); +static gboolean timeout_expire_cb(gpointer user_data); /*****************************************************************************/ @@ -102,6 +110,7 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, guint32 ifa_flags; guint8 plen; guint i; + const gint32 now_sec = nm_utils_get_monotonic_timestamp_sec(); l3cd = nm_l3_config_data_new(multi_idx, ifindex); @@ -129,12 +138,17 @@ nm_ndisc_data_to_l3cd(NMDedupMultiIndex * multi_idx, NMPlatformIP6Address a; a = (NMPlatformIP6Address){ - .ifindex = ifindex, - .address = ndisc_addr->address, - .plen = plen, - .timestamp = ndisc_addr->timestamp, - .lifetime = ndisc_addr->lifetime, - .preferred = MIN(ndisc_addr->lifetime, ndisc_addr->preferred), + .ifindex = ifindex, + .address = ndisc_addr->address, + .plen = plen, + .timestamp = now_sec, + .lifetime = _nm_ndisc_lifetime_from_expiry(((gint64) now_sec) * 1000, + ndisc_addr->expiry_msec, + TRUE), + .preferred = _nm_ndisc_lifetime_from_expiry( + ((gint64) now_sec) * 1000, + NM_MIN(ndisc_addr->expiry_msec, ndisc_addr->expiry_preferred_msec), + TRUE), .addr_source = NM_IP_CONFIG_SOURCE_NDISC, .n_ifa_flags = ifa_flags, }; @@ -220,77 +234,40 @@ _preference_to_priority(NMIcmpv6RouterPref pref) /*****************************************************************************/ -/* we rely on the fact, that _EXPIRY_INFINITY > any other valid gint64 timestamps. */ -#define _EXPIRY_INFINITY G_MAXINT64 - -static gint64 -get_expiry_time(guint32 timestamp, guint32 lifetime) -{ - nm_assert(timestamp > 0); - nm_assert(timestamp <= G_MAXINT32); - - if (lifetime == NM_NDISC_INFINITY) - return _EXPIRY_INFINITY; - return ((gint64) timestamp) + ((gint64) lifetime); -} - -#define get_expiry(item) \ - ({ \ - typeof(item) _item = (item); \ - nm_assert(_item); \ - get_expiry_time(_item->timestamp, _item->lifetime); \ - }) - -#define get_expiry_half(item) \ - ({ \ - typeof(item) _item = (item); \ - nm_assert(_item); \ - (_item->lifetime == NM_NDISC_INFINITY) \ - ? _EXPIRY_INFINITY \ - : get_expiry_time(_item->timestamp, _item->lifetime / 2); \ - }) - -#define get_expiry_preferred(item) \ - ({ \ - typeof(item) _item = (item); \ - nm_assert(_item); \ - get_expiry_time(_item->timestamp, _item->preferred); \ - }) - static gboolean -expiry_next(gint32 now_s, gint64 expiry_timestamp, gint32 *nextevent) +expiry_next(gint64 now_msec, gint64 expiry_msec, gint64 *next_msec) { - gint32 e; - - if (expiry_timestamp == _EXPIRY_INFINITY) + if (expiry_msec == NM_NDISC_EXPIRY_INFINITY) return TRUE; - e = MIN(expiry_timestamp, ((gint64)(G_MAXINT32 - 1))); - if (now_s >= e) + + if (expiry_msec <= now_msec) { + /* expired. */ return FALSE; - if (nextevent) { - if (*nextevent > e) - *nextevent = e; } + + if (next_msec) { + if (*next_msec > expiry_msec) + *next_msec = expiry_msec; + } + + /* the timestamp is good (not yet expired) */ return TRUE; } static const char * -_get_exp(char *buf, gsize buf_size, gint64 now_ns, gint64 expiry_time) +_get_exp(char *buf, gsize buf_size, gint64 now_msec, gint64 expiry_time) { int l; - if (expiry_time == _EXPIRY_INFINITY) + if (expiry_time == NM_NDISC_EXPIRY_INFINITY) return "permanent"; - l = g_snprintf(buf, - buf_size, - "%.4f", - ((double) ((expiry_time * NM_UTILS_NSEC_PER_SEC) - now_ns)) - / ((double) NM_UTILS_NSEC_PER_SEC)); + l = g_snprintf(buf, buf_size, "%.3f", ((double) (expiry_time - now_msec)) / 1000); nm_assert(l < buf_size); return buf; } -#define get_exp(buf, now_ns, item) _get_exp((buf), G_N_ELEMENTS(buf), (now_ns), (get_expiry(item))) +#define get_exp(buf, now_msec, item) \ + _get_exp((buf), G_N_ELEMENTS(buf), (now_msec), (item)->expiry_msec) /*****************************************************************************/ @@ -361,17 +338,16 @@ _ASSERT_data_gateways(const NMNDiscDataInternal *data) const NMNDiscGateway *item = &g_array_index(data->gateways, NMNDiscGateway, i); nm_assert(!IN6_IS_ADDR_UNSPECIFIED(&item->address)); - nm_assert(item->timestamp > 0 && item->timestamp <= G_MAXINT32); for (j = 0; j < i; j++) { const NMNDiscGateway *item2 = &g_array_index(data->gateways, NMNDiscGateway, j); nm_assert(!IN6_ARE_ADDR_EQUAL(&item->address, &item2->address)); } - nm_assert(item->lifetime > 0); - if (i > 0) + if (i > 0) { nm_assert(_preference_to_priority(item_prev->preference) >= _preference_to_priority(item->preference)); + } item_prev = item; } @@ -417,7 +393,7 @@ nm_ndisc_emit_config_change(NMNDisc *self, NMNDiscConfigMap changed) /*****************************************************************************/ gboolean -nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new) +nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new_item, gint64 now_msec) { NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; guint i; @@ -426,41 +402,46 @@ nm_ndisc_add_gateway(NMNDisc *ndisc, const NMNDiscGateway *new) for (i = 0; i < rdata->gateways->len;) { NMNDiscGateway *item = &g_array_index(rdata->gateways, NMNDiscGateway, i); - if (IN6_ARE_ADDR_EQUAL(&item->address, &new->address)) { - if (new->lifetime == 0) { + if (IN6_ARE_ADDR_EQUAL(&item->address, &new_item->address)) { + if (new_item->expiry_msec <= now_msec) { g_array_remove_index(rdata->gateways, i); _ASSERT_data_gateways(rdata); return TRUE; } - if (item->preference != new->preference) { + if (item->preference != new_item->preference) { g_array_remove_index(rdata->gateways, i); continue; } - if (get_expiry(item) == get_expiry(new)) + if (item->expiry_msec == new_item->expiry_msec) return FALSE; - *item = *new; + item->expiry_msec = new_item->expiry_msec; _ASSERT_data_gateways(rdata); return TRUE; } /* Put before less preferable gateways. */ - if (_preference_to_priority(item->preference) < _preference_to_priority(new->preference) + if (_preference_to_priority(item->preference) + < _preference_to_priority(new_item->preference) && insert_idx == G_MAXUINT) insert_idx = i; i++; } - if (new->lifetime) { - g_array_insert_val(rdata->gateways, - insert_idx == G_MAXUINT ? rdata->gateways->len : insert_idx, - *new); - } + if (rdata->gateways->len >= _SIZE_MAX_GATEWAYS) + return FALSE; + + if (new_item->expiry_msec <= now_msec) + return FALSE; + + g_array_insert_val(rdata->gateways, + insert_idx == G_MAXUINT ? rdata->gateways->len : insert_idx, + *new_item); _ASSERT_data_gateways(rdata); - return !!new->lifetime; + return TRUE; } /** @@ -513,25 +494,27 @@ complete_address(NMNDisc *ndisc, NMNDiscAddress *addr) return TRUE; } - _LOGW("complete-address: can't generate a new EUI-64 address"); + _LOGW("complete-address: can't generate a new_item EUI-64 address"); return FALSE; } static gboolean -nm_ndisc_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s, gboolean from_ra) +nm_ndisc_add_address(NMNDisc * ndisc, + const NMNDiscAddress *new_item, + gint64 now_msec, + gboolean from_ra) { NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); NMNDiscDataInternal *rdata = &priv->rdata; - NMNDiscAddress new2; + NMNDiscAddress * new2; NMNDiscAddress * existing = NULL; guint i; - nm_assert(new); - nm_assert(new->timestamp > 0 && new->timestamp < G_MAXINT32); - nm_assert(!IN6_IS_ADDR_UNSPECIFIED(&new->address)); - nm_assert(!IN6_IS_ADDR_LINKLOCAL(&new->address)); - nm_assert(new->preferred <= new->lifetime); - nm_assert(!from_ra || now_s > 0); + nm_assert(new_item); + nm_assert(!IN6_IS_ADDR_UNSPECIFIED(&new_item->address)); + nm_assert(!IN6_IS_ADDR_LINKLOCAL(&new_item->address)); + nm_assert(new_item->expiry_preferred_msec <= new_item->expiry_msec); + nm_assert((!!from_ra) == (now_msec > 0)); for (i = 0; i < rdata->addresses->len; i++) { NMNDiscAddress *item = &g_array_index(rdata->addresses, NMNDiscAddress, i); @@ -539,12 +522,12 @@ nm_ndisc_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s, gb if (from_ra) { /* RFC4862 5.5.3.d, we find an existing address with the same prefix. * (note that all prefixes at this point have implicitly length /64). */ - if (memcmp(&item->address, &new->address, 8) == 0) { + if (memcmp(&item->address, &new_item->address, 8) == 0) { existing = item; break; } } else { - if (IN6_ARE_ADDR_EQUAL(&item->address, &new->address)) { + if (IN6_ARE_ADDR_EQUAL(&item->address, &new_item->address)) { existing = item; break; } @@ -552,67 +535,60 @@ nm_ndisc_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s, gb } if (existing) { - if (from_ra) { - const gint32 NM_NDISC_PREFIX_LFT_MIN = 7200; /* seconds, RFC4862 5.5.3.e */ - gint64 old_expiry_lifetime, old_expiry_preferred; - - old_expiry_lifetime = get_expiry(existing); - old_expiry_preferred = get_expiry_preferred(existing); + gint64 new_expiry_preferred_msec; + gint64 new_expiry_msec; - if (new->lifetime == NM_NDISC_INFINITY) - existing->lifetime = NM_NDISC_INFINITY; + if (from_ra) { + if (new_item->expiry_msec == NM_NDISC_EXPIRY_INFINITY) + new_expiry_msec = NM_NDISC_EXPIRY_INFINITY; else { - gint64 new_lifetime, remaining_lifetime; + const gint64 NDISC_PREFIX_LFT_MIN_MSEC = 7200 * 1000; /* RFC4862 5.5.3.e */ + gint64 new_lifetime; + gint64 existing_lifetime; - /* see RFC4862 5.5.3.e */ - if (existing->lifetime == NM_NDISC_INFINITY) - remaining_lifetime = G_MAXINT64; + new_lifetime = new_item->expiry_msec - now_msec; + if (existing->expiry_msec == NM_NDISC_EXPIRY_INFINITY) + existing_lifetime = G_MAXINT64; else - remaining_lifetime = ((gint64) existing->timestamp) - + ((gint64) existing->lifetime) - ((gint64) now_s); - new_lifetime = - ((gint64) new->timestamp) + ((gint64) new->lifetime) - ((gint64) now_s); - - if (new_lifetime > (gint64) NM_NDISC_PREFIX_LFT_MIN - || new_lifetime > remaining_lifetime) { - existing->timestamp = now_s; - existing->lifetime = CLAMP(new_lifetime, (gint64) 0, (gint64)(G_MAXUINT32 - 1)); - } else if (remaining_lifetime <= (gint64) NM_NDISC_PREFIX_LFT_MIN) { + existing_lifetime = existing->expiry_msec - now_msec; + + /* see RFC4862 5.5.3.e */ + if (new_lifetime >= NDISC_PREFIX_LFT_MIN_MSEC + || new_lifetime >= existing_lifetime) { + /* either extend the lifetime of the new_item lifetime is longer than + * NDISC_PREFIX_LFT_MIN_MSEC. */ + new_expiry_msec = new_item->expiry_msec; + } else if (existing_lifetime <= NDISC_PREFIX_LFT_MIN_MSEC) { /* keep the current lifetime. */ + new_expiry_msec = existing->expiry_msec; } else { - existing->timestamp = now_s; - existing->lifetime = NM_NDISC_PREFIX_LFT_MIN; + /* trim the current lifetime to NDISC_PREFIX_LFT_MIN_MSEC. */ + new_expiry_msec = now_msec + NDISC_PREFIX_LFT_MIN_MSEC; } } - if (new->preferred == NM_NDISC_INFINITY) { - nm_assert(existing->lifetime == NM_NDISC_INFINITY); - existing->preferred = new->preferred; - } else { - existing->preferred = NM_CLAMP(((gint64) new->timestamp) + ((gint64) new->preferred) - - ((gint64) existing->timestamp), - 0, - G_MAXUINT32 - 1); - if (existing->lifetime != NM_NDISC_INFINITY) - existing->preferred = MIN(existing->preferred, existing->lifetime); + new_expiry_preferred_msec = + NM_MIN(new_item->expiry_preferred_msec, new_item->expiry_msec); + new_expiry_preferred_msec = NM_MIN(new_expiry_preferred_msec, new_expiry_msec); + } else { + if (new_item->expiry_msec <= now_msec) { + g_array_remove_index(rdata->addresses, i); + return TRUE; } - return old_expiry_lifetime != get_expiry(existing) - || old_expiry_preferred != get_expiry_preferred(existing); - } - - if (new->lifetime == 0) { - g_array_remove_index(rdata->addresses, i); - return TRUE; + new_expiry_msec = new_item->expiry_msec; + new_expiry_preferred_msec = + NM_MIN(new_item->expiry_preferred_msec, new_item->expiry_msec); } - if (get_expiry(existing) == get_expiry(new) - && get_expiry_preferred(existing) == get_expiry_preferred(new)) + /* the dad_counter does not get modified. */ + if (new_expiry_msec == existing->expiry_msec + && new_expiry_preferred_msec == existing->expiry_preferred_msec) { return FALSE; + } - existing->timestamp = new->timestamp; - existing->lifetime = new->lifetime; - existing->preferred = new->preferred; + existing->expiry_msec = new_expiry_msec; + existing->expiry_preferred_msec = new_expiry_preferred_msec; return TRUE; } @@ -620,39 +596,45 @@ nm_ndisc_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s, gb * what the kernel does, because it considers *all* addresses (including * static and other temporary addresses). **/ - if (priv->max_addresses && rdata->addresses->len >= priv->max_addresses) + if (rdata->addresses->len >= priv->max_addresses) return FALSE; - if (new->lifetime == 0) + if (new_item->expiry_msec <= now_msec) return FALSE; + new2 = nm_g_array_append_new(rdata->addresses, NMNDiscAddress); + + *new2 = *new_item; + + new2->expiry_preferred_msec = NM_MIN(new2->expiry_preferred_msec, new2->expiry_msec); + if (from_ra) { - new2 = *new; - new2.dad_counter = 0; - if (!complete_address(ndisc, &new2)) + new2->dad_counter = 0; + if (!complete_address(ndisc, new2)) { + g_array_set_size(rdata->addresses, rdata->addresses->len - 1); return FALSE; - new = &new2; + } } - g_array_append_val(rdata->addresses, *new); return TRUE; } gboolean -nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new, gint32 now_s) +nm_ndisc_complete_and_add_address(NMNDisc *ndisc, const NMNDiscAddress *new_item, gint64 now_msec) { - return nm_ndisc_add_address(ndisc, new, now_s, TRUE); + return nm_ndisc_add_address(ndisc, new_item, now_msec, TRUE); } gboolean -nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new) +nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new_item, gint64 now_msec) { NMNDiscPrivate * priv; NMNDiscDataInternal *rdata; guint i; guint insert_idx = G_MAXUINT; + gboolean changed = FALSE; - if (new->plen == 0 || new->plen > 128) { + if (new_item->plen == 0 || new_item->plen > 128) { /* Only expect non-default routes. The router has no idea what the * local configuration or user preferences are, so sending routes * with a prefix length of 0 must be ignored by NMNDisc. @@ -669,41 +651,51 @@ nm_ndisc_add_route(NMNDisc *ndisc, const NMNDiscRoute *new) for (i = 0; i < rdata->routes->len;) { NMNDiscRoute *item = &g_array_index(rdata->routes, NMNDiscRoute, i); - if (IN6_ARE_ADDR_EQUAL(&item->network, &new->network) && item->plen == new->plen) { - if (new->lifetime == 0) { + if (IN6_ARE_ADDR_EQUAL(&item->network, &new_item->network) + && item->plen == new_item->plen) { + if (new_item->expiry_msec <= now_msec) { g_array_remove_index(rdata->routes, i); return TRUE; } - if (item->preference != new->preference) { + if (item->preference != new_item->preference) { g_array_remove_index(rdata->routes, i); + changed = TRUE; continue; } - if (get_expiry(item) == get_expiry(new) - && IN6_ARE_ADDR_EQUAL(&item->gateway, &new->gateway)) + if (item->expiry_msec == new_item->expiry_msec + && IN6_ARE_ADDR_EQUAL(&item->gateway, &new_item->gateway)) return FALSE; - *item = *new; + item->expiry_msec = new_item->expiry_msec; + item->gateway = new_item->gateway; return TRUE; } /* Put before less preferable routes. */ - if (_preference_to_priority(item->preference) < _preference_to_priority(new->preference) + if (_preference_to_priority(item->preference) + < _preference_to_priority(new_item->preference) && insert_idx == G_MAXUINT) insert_idx = i; i++; } - if (new->lifetime) { - g_array_insert_val(rdata->routes, insert_idx == G_MAXUINT ? 0u : insert_idx, *new); + if (rdata->routes->len >= _SIZE_MAX_ROUTES) + return FALSE; + + if (new_item->expiry_msec <= now_msec) { + nm_assert(!changed); + return FALSE; } - return !!new->lifetime; + + g_array_insert_val(rdata->routes, insert_idx == G_MAXUINT ? 0u : insert_idx, *new_item); + return TRUE; } gboolean -nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new) +nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new_item, gint64 now_msec) { NMNDiscPrivate * priv; NMNDiscDataInternal *rdata; @@ -715,28 +707,33 @@ nm_ndisc_add_dns_server(NMNDisc *ndisc, const NMNDiscDNSServer *new) for (i = 0; i < rdata->dns_servers->len; i++) { NMNDiscDNSServer *item = &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); - if (IN6_ARE_ADDR_EQUAL(&item->address, &new->address)) { - if (new->lifetime == 0) { + if (IN6_ARE_ADDR_EQUAL(&item->address, &new_item->address)) { + if (new_item->expiry_msec <= now_msec) { g_array_remove_index(rdata->dns_servers, i); return TRUE; } - if (get_expiry(item) == get_expiry(new)) + if (item->expiry_msec == new_item->expiry_msec) return FALSE; - *item = *new; + item->expiry_msec = new_item->expiry_msec; return TRUE; } } - if (new->lifetime) - g_array_append_val(rdata->dns_servers, *new); - return !!new->lifetime; + if (rdata->dns_servers->len >= _SIZE_MAX_DNS_SERVERS) + return FALSE; + + if (new_item->expiry_msec <= now_msec) + return FALSE; + + g_array_append_val(rdata->dns_servers, *new_item); + return TRUE; } -/* Copies new->domain if 'new' is added to the dns_domains list */ +/* Copies new_item->domain if 'new_item' is added to the dns_domains list */ gboolean -nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new) +nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new_item, gint64 now_msec) { NMNDiscPrivate * priv; NMNDiscDataInternal *rdata; @@ -749,101 +746,155 @@ nm_ndisc_add_dns_domain(NMNDisc *ndisc, const NMNDiscDNSDomain *new) for (i = 0; i < rdata->dns_domains->len; i++) { item = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); - if (!g_strcmp0(item->domain, new->domain)) { - if (new->lifetime == 0) { + if (nm_streq(item->domain, new_item->domain)) { + if (new_item->expiry_msec <= now_msec) { g_array_remove_index(rdata->dns_domains, i); return TRUE; } - if (get_expiry(item) == get_expiry(new)) + if (item->expiry_msec == new_item->expiry_msec) return FALSE; - item->timestamp = new->timestamp; - item->lifetime = new->lifetime; + item->expiry_msec = new_item->expiry_msec; return TRUE; } } - if (new->lifetime) { - g_array_append_val(rdata->dns_domains, *new); - item = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, rdata->dns_domains->len - 1); - item->domain = g_strdup(new->domain); - } - return !!new->lifetime; + if (rdata->dns_domains->len >= _SIZE_MAX_DNS_DOMAINS) + return FALSE; + + if (new_item->expiry_msec <= now_msec) + return FALSE; + + item = nm_g_array_append_new(rdata->dns_domains, NMNDiscDNSDomain); + *item = (NMNDiscDNSDomain){ + .domain = g_strdup(new_item->domain), + .expiry_msec = new_item->expiry_msec, + }; + return TRUE; } /*****************************************************************************/ -#define _MAYBE_WARN(...) \ - G_STMT_START \ - { \ - gboolean _different_message; \ - \ - _different_message = g_strcmp0(priv->last_error, error->message) != 0; \ - _NMLOG(_different_message ? LOGL_WARN : LOGL_DEBUG, __VA_ARGS__); \ - if (_different_message) { \ - nm_clear_g_free(&priv->last_error); \ - priv->last_error = g_strdup(error->message); \ - } \ - } \ +#define _MAYBE_WARN(...) \ + G_STMT_START \ + { \ + gboolean _different_message; \ + \ + _different_message = !nm_streq0(priv->last_error, error->message); \ + _NMLOG(_different_message ? LOGL_WARN : LOGL_DEBUG, __VA_ARGS__); \ + if (_different_message) { \ + nm_clear_g_free(&priv->last_error); \ + priv->last_error = g_strdup(error->message); \ + } \ + } \ G_STMT_END -static gboolean -send_rs_timeout(NMNDisc *ndisc) +static gint32 +solicit_retransmit_time_jitter(gint32 solicit_retransmit_time_msec) { - nm_auto_pop_netns NMPNetns *netns = NULL; - NMNDiscClass * klass = NM_NDISC_GET_CLASS(ndisc); - NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); - GError * error = NULL; + gint32 ten_percent; - priv->send_rs_id = 0; + nm_assert(solicit_retransmit_time_msec > 0); + nm_assert(solicit_retransmit_time_msec < 3 * RFC7559_MRT * 1000); - if (!nm_ndisc_netns_push(ndisc, &netns)) - return G_SOURCE_REMOVE; + /* Add a ±10% jitter. + * + * This is the "RAND" parameter from https://tools.ietf.org/html/rfc3315#section-14 + * as requested by RFC7559. */ + + ten_percent = NM_MAX(1, solicit_retransmit_time_msec / 10); - if (klass->send_rs(ndisc, &error)) { - _LOGD("router solicitation sent"); - priv->solicitations_left--; + return solicit_retransmit_time_msec - ten_percent + + ((gint32)(g_random_int() % (2u * ((guint32) ten_percent)))); +} + +static gboolean +solicit_timer_cb(gpointer user_data) +{ + const gint32 TIMEOUT_APPROX_THRESHOLD_SEC = 10000; + nm_auto_pop_netns NMPNetns *netns = NULL; + NMNDisc * ndisc = user_data; + NMNDiscClass * klass = NM_NDISC_GET_CLASS(ndisc); + NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + gs_free_error GError *error = NULL; + gint32 timeout_msec; + + if (!nm_ndisc_netns_push(ndisc, &netns)) { + nm_utils_error_set(&error, + NM_UTILS_ERROR_UNKNOWN, + "failure to switch netns for soliciting routers"); + } else + klass->send_rs(ndisc, &error); + + if (error) + _MAYBE_WARN("solicit: failure sending router solicitation: %s", error->message); + else { + _LOGT("solicit: router solicitation sent"); nm_clear_g_free(&priv->last_error); - } else { - _MAYBE_WARN("failure sending router solicitation: %s", error->message); - g_clear_error(&error); } - priv->last_rs = nm_utils_get_monotonic_timestamp_sec(); - if (priv->solicitations_left > 0) { - _LOGD("scheduling router solicitation retry in %d seconds.", - (int) priv->router_solicitation_interval); - priv->send_rs_id = g_timeout_add_seconds(priv->router_solicitation_interval, - (GSourceFunc) send_rs_timeout, - ndisc); + /* https://tools.ietf.org/html/rfc4861#section-6.3.7 describes how to send solicitations: + * + * > ... a host SHOULD transmit up to MAX_RTR_SOLICITATIONS Router Solicitation messages, + * > each separated by at least RTR_SOLICITATION_INTERVAL seconds. + * + * but this was extended by https://tools.ietf.org/html/rfc7559#section-2 to send continuously + * and with exponential backoff (detailed the algorithm in https://tools.ietf.org/html/rfc3315#section-14). + * We do RFC7559. + */ + if (priv->solicit_retransmit_time_msec == 0) { + G_STATIC_ASSERT(RFC7559_IRT == NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL); + priv->solicit_retransmit_time_msec = solicit_retransmit_time_jitter(RFC7559_IRT * 1000); + timeout_msec = priv->solicit_retransmit_time_msec; } else { - _LOGD("did not receive a router advertisement after %d solicitations.", - (int) priv->router_solicitations); + priv->solicit_retransmit_time_msec += + solicit_retransmit_time_jitter(priv->solicit_retransmit_time_msec); + timeout_msec = priv->solicit_retransmit_time_msec; + if (priv->solicit_retransmit_time_msec > RFC7559_MRT * 1000) { + priv->solicit_retransmit_time_msec = RFC7559_MRT * 1000; + timeout_msec = solicit_retransmit_time_jitter(priv->solicit_retransmit_time_msec); + } } - return G_SOURCE_REMOVE; + _LOGD("solicit: schedule sending next solicitation in%s %.3f seconds", + timeout_msec / 1000 >= TIMEOUT_APPROX_THRESHOLD_SEC ? " about" : "", + ((double) timeout_msec) / 1000); + + nm_clear_g_source_inst(&priv->solicit_timer_source); + priv->solicit_timer_source = nm_g_timeout_add_source_approx(timeout_msec, + TIMEOUT_APPROX_THRESHOLD_SEC, + solicit_timer_cb, + ndisc); + return G_SOURCE_CONTINUE; } static void -solicit_routers(NMNDisc *ndisc) +solicit_timer_start(NMNDisc *ndisc) { NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); - gint32 now, next; - gint64 t; + gint32 delay_msec; - if (priv->send_rs_id) - return; + /* rfc4861, Section 6.3.7: + * + * We should randomly wait up to NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY (1 second) + * before sending the first RS. RFC4861 is from 2007, I don't think 1 second is + * a suitable delay in 2021. Wait only up to 250 msec instead. */ + + delay_msec = + g_random_int() % ((guint32)(NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY * 1000 / 4)); - now = nm_utils_get_monotonic_timestamp_sec(); - priv->solicitations_left = priv->router_solicitations; + _LOGD("solicit: schedule sending first solicitation (of %d) in %.3f seconds", + priv->router_solicitations, + ((double) delay_msec) / 1000); - t = (((gint64) priv->last_rs) + priv->router_solicitation_interval) - now; - next = CLAMP(t, 0, G_MAXINT32); - _LOGD("scheduling explicit router solicitation request in %" G_GINT32_FORMAT " seconds.", next); - priv->send_rs_id = g_timeout_add_seconds((guint32) next, (GSourceFunc) send_rs_timeout, ndisc); + priv->solicit_retransmit_time_msec = 0; + nm_clear_g_source_inst(&priv->solicit_timer_source); + priv->solicit_timer_source = nm_g_timeout_add_source(delay_msec, solicit_timer_cb, ndisc); } +/*****************************************************************************/ + static gboolean announce_router(NMNDisc *ndisc) { @@ -946,12 +997,16 @@ nm_ndisc_set_config(NMNDisc * ndisc, } for (i = 0; i < dns_servers->len; i++) { - if (nm_ndisc_add_dns_server(ndisc, &g_array_index(dns_servers, NMNDiscDNSServer, i))) + if (nm_ndisc_add_dns_server(ndisc, + &g_array_index(dns_servers, NMNDiscDNSServer, i), + 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))) + if (nm_ndisc_add_dns_domain(ndisc, + &g_array_index(dns_domains, NMNDiscDNSDomain, i), + G_MININT64)) changed = TRUE; } @@ -999,7 +1054,7 @@ nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid) _LOGD("IPv6 interface identifier changed, flushing addresses"); g_array_remove_range(rdata->addresses, 0, rdata->addresses->len); nm_ndisc_emit_config_change(ndisc, NM_NDISC_CONFIG_ADDRESSES); - solicit_routers(ndisc); + solicit_timer_start(ndisc); } return TRUE; } @@ -1008,13 +1063,13 @@ nm_ndisc_set_iid(NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid) } static gboolean -ndisc_ra_timeout_cb(gpointer user_data) +ra_timeout_cb(gpointer user_data) { NMNDisc *ndisc = NM_NDISC(user_data); nm_clear_g_source_inst(&NM_NDISC_GET_PRIVATE(ndisc)->ra_timeout_source); g_signal_emit(ndisc, signals[RA_TIMEOUT_SIGNAL], 0); - return G_SOURCE_REMOVE; + return G_SOURCE_CONTINUE; } void @@ -1053,15 +1108,10 @@ nm_ndisc_start(NMNDisc *ndisc) timeout_msec = priv->ra_timeout * 1000u; else timeout_msec = G_MAXUINT; - priv->ra_timeout_source = nm_g_timeout_source_new(timeout_msec, - G_PRIORITY_DEFAULT, - ndisc_ra_timeout_cb, - ndisc, - NULL); - g_source_attach(priv->ra_timeout_source, NULL); + priv->ra_timeout_source = nm_g_timeout_add_source(timeout_msec, ra_timeout_cb, ndisc); } - solicit_routers(ndisc); + solicit_timer_start(ndisc); return; } @@ -1099,20 +1149,16 @@ nm_ndisc_stop(NMNDisc *ndisc) g_array_set_size(rdata->dns_domains, 0); priv->rdata.public.hop_limit = 64; - /* Start at very low number so that last_rs - router_solicitation_interval - * is much lower than nm_utils_get_monotonic_timestamp_sec() at startup. - */ - priv->last_rs = G_MININT32; nm_clear_g_source_inst(&priv->ra_timeout_source); - nm_clear_g_source(&priv->send_rs_id); nm_clear_g_source(&priv->send_ra_id); nm_clear_g_free(&priv->last_error); - nm_clear_g_source(&priv->timeout_id); + nm_clear_g_source_inst(&priv->timeout_expire_source); + + priv->solicit_retransmit_time_msec = 0; + nm_clear_g_source_inst(&priv->solicit_timer_source); - priv->solicitations_left = 0; priv->announcements_left = 0; - priv->last_rs = G_MININT32; priv->last_ra = G_MININT32; } @@ -1189,15 +1235,15 @@ _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed) NMNDiscDataInternal *rdata; guint i; char changedstr[CONFIG_MAP_MAX_STR]; - char addrstr[INET6_ADDRSTRLEN]; + char addrstr[NM_UTILS_INET_ADDRSTRLEN]; char str_pref[35]; char str_exp[100]; - gint64 now_ns; + gint64 now_msec; if (!_LOGD_ENABLED()) return; - now_ns = nm_utils_get_monotonic_timestamp_nsec(); + now_msec = nm_utils_get_monotonic_timestamp_msec(); priv = NM_NDISC_GET_PRIVATE(ndisc); rdata = &priv->rdata; @@ -1214,215 +1260,300 @@ _config_changed_log(NMNDisc *ndisc, NMNDiscConfigMap changed) _LOGD(" retrans timer : %u", (guint) rdata->public.retrans_timer_ms); for (i = 0; i < rdata->gateways->len; i++) { - NMNDiscGateway *gateway = &g_array_index(rdata->gateways, NMNDiscGateway, i); + const NMNDiscGateway *gateway = &g_array_index(rdata->gateways, NMNDiscGateway, i); - inet_ntop(AF_INET6, &gateway->address, addrstr, sizeof(addrstr)); _LOGD(" gateway %s pref %s exp %s", - addrstr, + _nm_utils_inet6_ntop(&gateway->address, addrstr), nm_icmpv6_router_pref_to_string(gateway->preference, str_pref, sizeof(str_pref)), - get_exp(str_exp, now_ns, gateway)); + get_exp(str_exp, now_msec, gateway)); } for (i = 0; i < rdata->addresses->len; i++) { const NMNDiscAddress *address = &g_array_index(rdata->addresses, NMNDiscAddress, i); - inet_ntop(AF_INET6, &address->address, addrstr, sizeof(addrstr)); - _LOGD(" address %s exp %s", addrstr, get_exp(str_exp, now_ns, address)); + _LOGD(" address %s exp %s", + _nm_utils_inet6_ntop(&address->address, addrstr), + get_exp(str_exp, now_msec, address)); } for (i = 0; i < rdata->routes->len; i++) { - NMNDiscRoute *route = &g_array_index(rdata->routes, NMNDiscRoute, i); - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + const NMNDiscRoute *route = &g_array_index(rdata->routes, NMNDiscRoute, i); + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - inet_ntop(AF_INET6, &route->network, addrstr, sizeof(addrstr)); _LOGD(" route %s/%u via %s pref %s exp %s", - addrstr, + _nm_utils_inet6_ntop(&route->network, addrstr), (guint) route->plen, _nm_utils_inet6_ntop(&route->gateway, sbuf), nm_icmpv6_router_pref_to_string(route->preference, str_pref, sizeof(str_pref)), - get_exp(str_exp, now_ns, route)); + get_exp(str_exp, now_msec, route)); } for (i = 0; i < rdata->dns_servers->len; i++) { - NMNDiscDNSServer *dns_server = &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); + const NMNDiscDNSServer *dns_server = + &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); - inet_ntop(AF_INET6, &dns_server->address, addrstr, sizeof(addrstr)); - _LOGD(" dns_server %s exp %s", addrstr, get_exp(str_exp, now_ns, dns_server)); + _LOGD(" dns_server %s exp %s", + _nm_utils_inet6_ntop(&dns_server->address, addrstr), + get_exp(str_exp, now_msec, dns_server)); } for (i = 0; i < rdata->dns_domains->len; i++) { - NMNDiscDNSDomain *dns_domain = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); + const NMNDiscDNSDomain *dns_domain = + &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); - _LOGD(" dns_domain %s exp %s", dns_domain->domain, get_exp(str_exp, now_ns, dns_domain)); + _LOGD(" dns_domain %s exp %s", dns_domain->domain, get_exp(str_exp, now_msec, dns_domain)); } } +/*****************************************************************************/ + +static gboolean +_array_set_size_max(GArray *array, guint size_max) +{ + nm_assert(array); + nm_assert(size_max > 0u); + + if (array->len <= size_max) + return FALSE; + + g_array_set_size(array, size_max); + return TRUE; +} + static void -clean_gateways(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *nextevent) +clean_gateways(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscDataInternal *rdata; + NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + NMNDiscGateway * arr; guint i; + guint j; - rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + if (rdata->gateways->len == 0) + return; - for (i = 0; i < rdata->gateways->len;) { - NMNDiscGateway *item = &g_array_index(rdata->gateways, NMNDiscGateway, i); + arr = &g_array_index(rdata->gateways, NMNDiscGateway, 0); - if (!expiry_next(now, get_expiry(item), nextevent)) { - g_array_remove_index(rdata->gateways, i); - *changed |= NM_NDISC_CONFIG_GATEWAYS; + for (i = 0, j = 0; i < rdata->gateways->len; i++) { + if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)) continue; - } + if (i != j) + arr[j] = arr[i]; + j++; + } - i++; + if (i != j) { + *changed |= NM_NDISC_CONFIG_GATEWAYS; + g_array_set_size(rdata->gateways, j); } + if (_array_set_size_max(rdata->gateways, _SIZE_MAX_GATEWAYS)) + *changed |= NM_NDISC_CONFIG_GATEWAYS; + _ASSERT_data_gateways(rdata); } static void -clean_addresses(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *nextevent) +clean_addresses(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscDataInternal *rdata; + NMNDiscPrivate * priv = NM_NDISC_GET_PRIVATE(ndisc); + NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + NMNDiscAddress * arr; guint i; + guint j; - rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + if (rdata->addresses->len == 0) + return; - for (i = 0; i < rdata->addresses->len;) { - const NMNDiscAddress *item = &g_array_index(rdata->addresses, NMNDiscAddress, i); + arr = &g_array_index(rdata->addresses, NMNDiscAddress, 0); - if (!expiry_next(now, get_expiry(item), nextevent)) { - g_array_remove_index(rdata->addresses, i); - *changed |= NM_NDISC_CONFIG_ADDRESSES; + for (i = 0, j = 0; i < rdata->addresses->len; i++) { + if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)) continue; - } + if (i != j) + arr[j] = arr[i]; + j++; + } - i++; + if (i != j) { + *changed = NM_NDISC_CONFIG_ADDRESSES; + g_array_set_size(rdata->addresses, j); } + + if (_array_set_size_max(rdata->gateways, priv->max_addresses)) + *changed |= NM_NDISC_CONFIG_ADDRESSES; } static void -clean_routes(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *nextevent) +clean_routes(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscDataInternal *rdata; + NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + NMNDiscRoute * arr; guint i; + guint j; - rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + if (rdata->routes->len == 0) + return; - for (i = 0; i < rdata->routes->len;) { - NMNDiscRoute *item = &g_array_index(rdata->routes, NMNDiscRoute, i); + arr = &g_array_index(rdata->routes, NMNDiscRoute, 0); - if (!expiry_next(now, get_expiry(item), nextevent)) { - g_array_remove_index(rdata->routes, i); - *changed |= NM_NDISC_CONFIG_ROUTES; + for (i = 0, j = 0; i < rdata->routes->len; i++) { + if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)) continue; - } + if (i != j) + arr[j] = arr[i]; + j++; + } - i++; + if (i != j) { + *changed |= NM_NDISC_CONFIG_ROUTES; + g_array_set_size(rdata->routes, j); } + + if (_array_set_size_max(rdata->gateways, _SIZE_MAX_ROUTES)) + *changed |= NM_NDISC_CONFIG_ROUTES; } static void -clean_dns_servers(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *nextevent) +clean_dns_servers(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscDataInternal *rdata; + NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + NMNDiscDNSServer * arr; guint i; + guint j; - rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + if (rdata->dns_servers->len == 0) + return; - for (i = 0; i < rdata->dns_servers->len;) { - NMNDiscDNSServer *item = &g_array_index(rdata->dns_servers, NMNDiscDNSServer, i); - gint64 refresh; + arr = &g_array_index(rdata->dns_servers, NMNDiscDNSServer, 0); - refresh = get_expiry_half(item); - if (refresh != _EXPIRY_INFINITY) { - if (!expiry_next(now, get_expiry(item), NULL)) { - g_array_remove_index(rdata->dns_servers, i); - *changed |= NM_NDISC_CONFIG_DNS_SERVERS; - continue; - } + for (i = 0, j = 0; i < rdata->dns_servers->len; i++) { + if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)) + continue; + if (i != j) + arr[j] = arr[i]; + j++; + } - if (now >= refresh) - solicit_routers(ndisc); - else if (*nextevent > refresh) - *nextevent = refresh; - } - i++; + if (i != j) { + *changed |= NM_NDISC_CONFIG_DNS_SERVERS; + g_array_set_size(rdata->dns_servers, j); } + + if (_array_set_size_max(rdata->gateways, _SIZE_MAX_DNS_SERVERS)) + *changed |= NM_NDISC_CONFIG_DNS_SERVERS; } static void -clean_dns_domains(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap *changed, gint32 *nextevent) +clean_dns_domains(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap *changed, gint64 *next_msec) { - NMNDiscDataInternal *rdata; + NMNDiscDataInternal *rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + NMNDiscDNSDomain * arr; guint i; + guint j; - rdata = &NM_NDISC_GET_PRIVATE(ndisc)->rdata; + if (rdata->dns_domains->len == 0) + return; - for (i = 0; i < rdata->dns_domains->len;) { - NMNDiscDNSDomain *item = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, i); - gint64 refresh; + arr = &g_array_index(rdata->dns_domains, NMNDiscDNSDomain, 0); - refresh = get_expiry_half(item); - if (refresh != _EXPIRY_INFINITY) { - if (!expiry_next(now, get_expiry(item), NULL)) { - g_array_remove_index(rdata->dns_domains, i); - *changed |= NM_NDISC_CONFIG_DNS_DOMAINS; - continue; - } + for (i = 0, j = 0; i < rdata->dns_domains->len; i++) { + if (!expiry_next(now_msec, arr[i].expiry_msec, next_msec)) + continue; - if (now >= refresh) - solicit_routers(ndisc); - else if (*nextevent > refresh) - *nextevent = refresh; + if (i != j) { + g_free(arr[j].domain); + arr[j] = arr[i]; + arr[i].domain = NULL; } - i++; + + j++; } -} -static gboolean timeout_cb(gpointer user_data); + if (i != 0) { + *changed |= NM_NDISC_CONFIG_DNS_DOMAINS; + g_array_set_size(rdata->dns_domains, j); + } + + if (_array_set_size_max(rdata->gateways, _SIZE_MAX_DNS_DOMAINS)) + *changed |= NM_NDISC_CONFIG_DNS_DOMAINS; +} static void -check_timestamps(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed) +check_timestamps(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed) { - NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); - /* Use a magic date in the distant future (~68 years) */ - gint32 nextevent = G_MAXINT32; + NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); + gint64 next_msec = G_MAXINT64; - nm_clear_g_source(&priv->timeout_id); + _LOGT("router-data: check for changed router advertisement data"); - clean_gateways(ndisc, now, &changed, &nextevent); - clean_addresses(ndisc, now, &changed, &nextevent); - clean_routes(ndisc, now, &changed, &nextevent); - clean_dns_servers(ndisc, now, &changed, &nextevent); - clean_dns_domains(ndisc, now, &changed, &nextevent); + clean_gateways(ndisc, now_msec, &changed, &next_msec); + clean_addresses(ndisc, now_msec, &changed, &next_msec); + clean_routes(ndisc, now_msec, &changed, &next_msec); + clean_dns_servers(ndisc, now_msec, &changed, &next_msec); + clean_dns_domains(ndisc, now_msec, &changed, &next_msec); - if (nextevent != G_MAXINT32) { - if (nextevent <= now) - g_return_if_reached(); - _LOGD("scheduling next now/lifetime check: %d seconds", (int) (nextevent - now)); - priv->timeout_id = g_timeout_add_seconds(nextevent - now, timeout_cb, ndisc); + nm_assert(next_msec > now_msec); + + nm_clear_g_source_inst(&priv->timeout_expire_source); + + if (next_msec == NM_NDISC_EXPIRY_INFINITY) + _LOGD("router-data: next lifetime expiration will happen: never"); + else { + const gint64 timeout_msec = NM_MIN(next_msec - now_msec, ((gint64) G_MAXINT32)); + const guint TIMEOUT_APPROX_THRESHOLD_SEC = 10000; + + _LOGD("router-data: next lifetime expiration will happen: in %s%.3f seconds", + (timeout_msec / 1000) >= TIMEOUT_APPROX_THRESHOLD_SEC ? " about" : "", + ((double) timeout_msec) / 1000); + + priv->timeout_expire_source = nm_g_timeout_add_source_approx(timeout_msec, + TIMEOUT_APPROX_THRESHOLD_SEC, + timeout_expire_cb, + ndisc); } - if (changed) + /* When we receive an RA, we don't disable solicitations entirely. Instead, + * we set the interval the maximum (RFC7559_MRT). + * + * This contradicts https://tools.ietf.org/html/rfc7559#section-2.1, which says + * that we SHOULD stop sending RS if we receive an RA -- but only on a multicast + * capable link and if the RA has a valid router lifetime. + * + * But we really want to recover from a dead router on the network, so we + * don't want to cease sending RS entirely. + * + * But we only re-schedule the timer if the current interval is not already + * "RFC7559_MRT * 1000". Otherwise, we already have a slow interval counter + * pending. */ + if (priv->solicit_retransmit_time_msec != RFC7559_MRT * 1000) { + gint32 timeout_msec; + + priv->solicit_retransmit_time_msec = RFC7559_MRT * 1000; + timeout_msec = solicit_retransmit_time_jitter(priv->solicit_retransmit_time_msec); + + _LOGD("solicit: schedule sending next (slow) solicitation in about %.3f seconds", + ((double) timeout_msec) / 1000); + + nm_clear_g_source_inst(&priv->solicit_timer_source); + priv->solicit_timer_source = + nm_g_timeout_add_source_approx(timeout_msec, 0, solicit_timer_cb, ndisc); + } + + if (changed != NM_NDISC_CONFIG_NONE) nm_ndisc_emit_config_change(ndisc, changed); } static gboolean -timeout_cb(gpointer user_data) +timeout_expire_cb(gpointer user_data) { - NMNDisc *self = user_data; - - NM_NDISC_GET_PRIVATE(self)->timeout_id = 0; - check_timestamps(self, nm_utils_get_monotonic_timestamp_sec(), 0); - return G_SOURCE_REMOVE; + check_timestamps(user_data, nm_utils_get_monotonic_timestamp_msec(), NM_NDISC_CONFIG_NONE); + return G_SOURCE_CONTINUE; } void -nm_ndisc_ra_received(NMNDisc *ndisc, gint32 now, NMNDiscConfigMap changed) +nm_ndisc_ra_received(NMNDisc *ndisc, gint64 now_msec, NMNDiscConfigMap changed) { NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); nm_clear_g_source_inst(&priv->ra_timeout_source); - nm_clear_g_source(&priv->send_rs_id); nm_clear_g_free(&priv->last_error); - check_timestamps(ndisc, now, changed); + check_timestamps(ndisc, now_msec, changed); } void @@ -1447,6 +1578,7 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps { NMNDisc * self = NM_NDISC(object); NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(self); + int i; switch (prop_id) { case PROP_PLATFORM: @@ -1488,7 +1620,14 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps break; case PROP_MAX_ADDRESSES: /* construct-only */ - priv->max_addresses = g_value_get_int(value); + i = g_value_get_int(value); + nm_assert(i >= 0); + priv->max_addresses = i; + + if (priv->max_addresses <= 0) + priv->max_addresses = _SIZE_MAX_ADDRESSES; + else if (priv->max_addresses > 3u * _SIZE_MAX_ADDRESSES) + priv->max_addresses = 3u * _SIZE_MAX_ADDRESSES; break; case PROP_RA_TIMEOUT: /* construct-only */ @@ -1532,11 +1671,6 @@ nm_ndisc_init(NMNDisc *ndisc) rdata->dns_domains = g_array_new(FALSE, FALSE, sizeof(NMNDiscDNSDomain)); g_array_set_clear_func(rdata->dns_domains, dns_domain_free); priv->rdata.public.hop_limit = 64; - - /* Start at very low number so that last_rs - router_solicitation_interval - * is much lower than nm_utils_get_monotonic_timestamp_sec() at startup. - */ - priv->last_rs = G_MININT32; } static void @@ -1546,11 +1680,11 @@ dispose(GObject *object) NMNDiscPrivate *priv = NM_NDISC_GET_PRIVATE(ndisc); nm_clear_g_source_inst(&priv->ra_timeout_source); - nm_clear_g_source(&priv->send_rs_id); + nm_clear_g_source_inst(&priv->solicit_timer_source); nm_clear_g_source(&priv->send_ra_id); nm_clear_g_free(&priv->last_error); - nm_clear_g_source(&priv->timeout_id); + nm_clear_g_source_inst(&priv->timeout_expire_source); G_OBJECT_CLASS(nm_ndisc_parent_class)->dispose(object); } @@ -1661,7 +1795,7 @@ nm_ndisc_class_init(NMNDiscClass *klass) "", 1, G_MAXINT32, - NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT, + NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); obj_properties[PROP_NODE_TYPE] = g_param_spec_int(NM_NDISC_NODE_TYPE, diff --git a/src/ndisc/nm-ndisc.h b/src/core/ndisc/nm-ndisc.h index 0578c45b..93aee4db 100644 --- a/src/ndisc/nm-ndisc.h +++ b/src/core/ndisc/nm-ndisc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ @@ -48,48 +48,91 @@ typedef enum { NM_NDISC_DHCP_LEVEL_MANAGED } NMNDiscDHCPLevel; -/* we rely on the fact that NM_NDISC_INFINITY is the largest possible - * time duration (G_MAXUINT32) and that the range of finite values - * goes from 0 to G_MAXUINT32-1. */ -#define NM_NDISC_INFINITY G_MAXUINT32 +#define NM_NDISC_INFINITY_U32 ((uint32_t) -1) -struct _NMNDiscGateway { +/* It's important that this is G_MAXINT64, so that we can meaningfully do + * MIN(e1, e2) to find the minimum expiry time (and properly handle if any + * of them is infinity). + * + * While usually you assign this to "expiry_msec", you might say the + * unit of it is milliseconds. But of course, infinity has not really a unit. */ +#define NM_NDISC_EXPIRY_INFINITY G_MAXINT64 + +/* in common cases, the expiry_msec tracks the timestamp in nm_utils_get_monotonic_timestamp_mses() + * timestamp when the item expires. + * + * When we configure an NMNDiscAddress to be announced via the router advertisement, + * then that address does not have a fixed expiry point in time, instead, the expiry + * really contains the lifetime from the moment when we send the router advertisement. + * In that case, the expiry_msec is more a "lifetime" that starts counting at timestamp + * zero. + * + * The unit is milliseconds (but of course, the timestamp is zero, so it doesn't really matter). */ +#define NM_NDISC_EXPIRY_BASE_TIMESTAMP ((gint64) 0) + +static inline gint64 +_nm_ndisc_lifetime_to_expiry(gint64 now_msec, guint32 lifetime) +{ + if (lifetime == NM_NDISC_INFINITY_U32) + return NM_NDISC_EXPIRY_INFINITY; + return now_msec + (((gint64) lifetime) * 1000); +} + +static inline gint64 +_nm_ndisc_lifetime_from_expiry(gint64 now_msec, gint64 expiry_msec, gboolean ceil) +{ + gint64 diff; + + if (expiry_msec == NM_NDISC_EXPIRY_INFINITY) + return NM_NDISC_INFINITY_U32; + + /* we don't expect nor handle integer overflow. The time stamp and expiry + * should be reasonably small so that it cannot happen. */ + + diff = expiry_msec - now_msec; + + if (diff <= 0) + return 0; + + if (ceil) { + /* we ceil() towards the next full second (instead of floor()). */ + diff += 999; + } + + return NM_MIN(diff / 1000, (gint64)(G_MAXUINT32 - 1)); +} + +/*****************************************************************************/ + +typedef struct _NMNDiscGateway { struct in6_addr address; - guint32 timestamp; - guint32 lifetime; + gint64 expiry_msec; NMIcmpv6RouterPref preference; -}; -typedef struct _NMNDiscGateway NMNDiscGateway; +} NMNDiscGateway; -struct _NMNDiscAddress { +typedef struct _NMNDiscAddress { struct in6_addr address; + gint64 expiry_msec; + gint64 expiry_preferred_msec; guint8 dad_counter; - guint32 timestamp; - guint32 lifetime; - guint32 preferred; -}; -typedef struct _NMNDiscAddress NMNDiscAddress; +} NMNDiscAddress; -struct _NMNDiscRoute { +typedef struct _NMNDiscRoute { struct in6_addr network; - guint8 plen; struct in6_addr gateway; - guint32 timestamp; - guint32 lifetime; + gint64 expiry_msec; NMIcmpv6RouterPref preference; -}; -typedef struct _NMNDiscRoute NMNDiscRoute; + guint8 plen; +} NMNDiscRoute; typedef struct { struct in6_addr address; - guint32 timestamp; - guint32 lifetime; + gint64 expiry_msec; } NMNDiscDNSServer; typedef struct { - char * domain; - guint32 timestamp; - guint32 lifetime; + char * domain; + gint64 expiry_msec; } NMNDiscDNSDomain; typedef enum { @@ -112,15 +155,17 @@ typedef enum { NM_NDISC_NODE_TYPE_ROUTER, } NMNDiscNodeType; -#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16 -#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861 MAX_RTR_SOLICITATIONS */ -#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4 /* RFC4861 RTR_SOLICITATION_INTERVAL */ -#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861 MAX_INITIAL_RTR_ADVERTISEMENTS */ -#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861 MIN_DELAY_BETWEEN_RAS */ -#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861 MAX_INITIAL_RTR_ADVERT_INTERVAL */ -#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861 MAX_RA_DELAY_TIME */ -#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861 MaxRtrAdvInterval default */ -#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */ +#define NM_NDISC_RFC4861_RTR_SOLICITATION_INTERVAL 4 /* seconds */ +#define NM_NDISC_RFC4861_MAX_RTR_SOLICITATION_DELAY 1 /* seconds */ + +#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16 +#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861, MAX_RTR_SOLICITATIONS */ +#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861, MAX_INITIAL_RTR_ADVERTISEMENTS */ +#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861, MIN_DELAY_BETWEEN_RAS */ +#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861, MAX_INITIAL_RTR_ADVERT_INTERVAL */ +#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861, MAX_RA_DELAY_TIME */ +#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861, MaxRtrAdvInterval default */ +#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */ struct _NMNDiscPrivate; struct _NMNDiscDataInternal; diff --git a/src/ndisc/tests/meson.build b/src/core/ndisc/tests/meson.build index 349eebba..6a2e70f0 100644 --- a/src/ndisc/tests/meson.build +++ b/src/core/ndisc/tests/meson.build @@ -1,11 +1,11 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_unit = 'test-ndisc-fake' exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) @@ -21,6 +21,6 @@ test = 'test-ndisc-linux' exe = executable( test, test + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/core/ndisc/tests/test-ndisc-fake.c b/src/core/ndisc/tests/test-ndisc-fake.c new file mode 100644 index 00000000..f201bc56 --- /dev/null +++ b/src/core/ndisc/tests/test-ndisc-fake.c @@ -0,0 +1,657 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "src/core/nm-default-daemon.h" + +#include <syslog.h> + +#include "ndisc/nm-ndisc.h" +#include "ndisc/nm-fake-ndisc.h" + +#include "platform/nm-fake-platform.h" + +#include "nm-test-utils-core.h" + +/*****************************************************************************/ + +static NMFakeNDisc * +ndisc_new(void) +{ + NMNDisc * ndisc; + const int ifindex = 1; + const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex); + NMUtilsIPv6IfaceId iid = {}; + + ndisc = nm_fake_ndisc_new(ifindex, ifname); + iid.id_u8[7] = 1; + nm_ndisc_set_iid(ndisc, iid); + g_assert(ndisc); + + return NM_FAKE_NDISC(ndisc); +} + +/*****************************************************************************/ + +static void +match_gateway(const NMNDiscData *rdata, + guint idx, + const char * addr, + gint64 expiry_msec, + NMIcmpv6RouterPref pref) +{ + const NMNDiscGateway *gw; + + g_assert(rdata); + g_assert_cmpint(idx, <, rdata->gateways_n); + g_assert(rdata->gateways); + + gw = &rdata->gateways[idx]; + + nmtst_assert_ip6_address(&gw->address, addr); + g_assert_cmpint(gw->expiry_msec, ==, expiry_msec); + g_assert_cmpint(gw->preference, ==, pref); +} + +#define match_address(rdata, idx, addr, _expiry_msec, _expiry_preferred_msec) \ + G_STMT_START \ + { \ + const NMNDiscData * _rdata = (rdata); \ + guint _idx = (idx); \ + const NMNDiscAddress *_a; \ + \ + g_assert(_rdata); \ + g_assert_cmpint(_idx, <, _rdata->addresses_n); \ + g_assert(_rdata->addresses); \ + \ + _a = &_rdata->addresses[_idx]; \ + \ + nmtst_assert_ip6_address(&_a->address, (addr)); \ + g_assert_cmpint(_a->expiry_msec, ==, (_expiry_msec)); \ + g_assert_cmpint(_a->expiry_preferred_msec, ==, (_expiry_preferred_msec)); \ + } \ + G_STMT_END + +#define match_route(rdata, idx, nw, pl, gw, _expiry_msec, pref) \ + G_STMT_START \ + { \ + const NMNDiscData * _rdata = (rdata); \ + guint _idx = (idx); \ + const NMNDiscRoute *_r; \ + int _plen = (pl); \ + \ + g_assert(_rdata); \ + g_assert_cmpint(_idx, <, _rdata->routes_n); \ + g_assert(_rdata->routes); \ + g_assert(_plen > 0 && _plen <= 128); \ + \ + _r = &_rdata->routes[idx]; \ + \ + nmtst_assert_ip6_address(&_r->network, (nw)); \ + g_assert_cmpint((int) _r->plen, ==, _plen); \ + nmtst_assert_ip6_address(&_r->gateway, (gw)); \ + g_assert_cmpint(_r->expiry_msec, ==, (_expiry_msec)); \ + g_assert_cmpint(_r->preference, ==, (pref)); \ + } \ + G_STMT_END + +static void +match_dns_server(const NMNDiscData *rdata, guint idx, const char *addr, gint64 expiry_msec) +{ + const NMNDiscDNSServer *dns; + + g_assert(rdata); + g_assert_cmpint(idx, <, rdata->dns_servers_n); + g_assert(rdata->dns_servers); + + dns = &rdata->dns_servers[idx]; + + nmtst_assert_ip6_address(&dns->address, addr); + g_assert_cmpint(dns->expiry_msec, ==, expiry_msec); +} + +static void +match_dns_domain(const NMNDiscData *rdata, guint idx, const char *domain, gint64 expiry_msec) +{ + const NMNDiscDNSDomain *dns; + + g_assert(rdata); + g_assert_cmpint(idx, <, rdata->dns_domains_n); + g_assert(rdata->dns_domains); + + dns = &rdata->dns_domains[idx]; + + g_assert_cmpstr(dns->domain, ==, domain); + g_assert_cmpint(dns->expiry_msec, ==, expiry_msec); +} + +/*****************************************************************************/ + +typedef struct { + GMainLoop *loop; + gint64 timestamp_msec_1; + guint counter; + guint rs_counter; + gint64 first_solicit_msec; + guint32 timeout_id; +} TestData; + +/*****************************************************************************/ + +static void +test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) +{ + NMNDiscConfigMap changed = changed_int; + + switch (data->counter++) { + case 0: + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS + | NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES + | NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS + | NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU); + g_assert_cmpint(rdata->dhcp_level, ==, NM_NDISC_DHCP_LEVEL_OTHERCONF); + match_gateway(rdata, + 0, + "fe80::1", + data->timestamp_msec_1 + 10000, + NM_ICMPV6_ROUTER_PREF_MEDIUM); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1 + 10000); + match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 10); + match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp_msec_1 + 10000); + match_dns_domain(rdata, 0, "foobar.com", data->timestamp_msec_1 + 3500); + + g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); + break; + case 1: + g_main_loop_quit(data->loop); + break; + default: + g_assert_not_reached(); + } +} + +static void +test_simple(void) +{ + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, + }; + guint id; + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_OTHERCONF, 4, 1500); + g_assert(id); + + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:a::", + 64, + "fe80::1", + now_msec + 10000, + now_msec + 10000, + 10); + nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 10000); + nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec + 3500); + + g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data); + + nm_ndisc_start(NM_NDISC(ndisc)); + nmtst_main_loop_run_assert(data.loop, 15000); + g_assert_cmpint(data.counter, ==, 2); +} + +/*****************************************************************************/ + +static void +test_everything_rs_sent(NMNDisc *ndisc, TestData *data) +{ + g_assert_cmpint(data->rs_counter, ==, 0); + data->rs_counter++; +} + +static void +test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) +{ + NMNDiscConfigMap changed = changed_int; + + if (data->counter == 0) { + g_assert_cmpint(data->rs_counter, ==, 1); + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS + | NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES + | NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS + | NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU); + match_gateway(rdata, + 0, + "fe80::1", + data->timestamp_msec_1 + 10000, + NM_ICMPV6_ROUTER_PREF_MEDIUM); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1 + 10000); + match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 10); + match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp_msec_1 + 10000); + match_dns_domain(rdata, 0, "foobar.com", data->timestamp_msec_1 + 10000); + } else if (data->counter == 1) { + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES + | NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_DNS_SERVERS + | NM_NDISC_CONFIG_DNS_DOMAINS); + + g_assert_cmpint(rdata->gateways_n, ==, 1); + match_gateway(rdata, + 0, + "fe80::2", + data->timestamp_msec_1 + 10000, + NM_ICMPV6_ROUTER_PREF_MEDIUM); + g_assert_cmpint(rdata->addresses_n, ==, 2); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1); + match_address(rdata, + 1, + "2001:db8:a:b::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1 + 10000); + g_assert_cmpint(rdata->routes_n, ==, 1); + match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 10000, 10); + g_assert_cmpint(rdata->dns_servers_n, ==, 1); + match_dns_server(rdata, 0, "2001:db8:c:c::2", data->timestamp_msec_1 + 10000); + g_assert_cmpint(rdata->dns_domains_n, ==, 1); + match_dns_domain(rdata, 0, "foobar2.com", data->timestamp_msec_1 + 10000); + + g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); + g_main_loop_quit(data->loop); + } else + g_assert_not_reached(); + + data->counter++; +} + +static void +test_everything(void) +{ + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, + }; + guint id; + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:a::", + 64, + "fe80::1", + now_msec + 10000, + now_msec + 10000, + 10); + nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 10000); + nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec + 10000); + + /* expire everything from the first RA in the second */ + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec, NM_ICMPV6_ROUTER_PREF_MEDIUM); + nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now_msec, now_msec, 0); + nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec); + nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now_msec); + + /* and add some new stuff */ + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_MEDIUM); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:b::", + 64, + "fe80::2", + now_msec + 10000, + now_msec + 10000, + 10); + nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::2", now_msec + 10000); + nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar2.com", now_msec + 10000); + + g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_everything_changed), &data); + g_signal_connect(ndisc, NM_FAKE_NDISC_RS_SENT, G_CALLBACK(test_everything_rs_sent), &data); + + nm_ndisc_start(NM_NDISC(ndisc)); + nmtst_main_loop_run_assert(data.loop, 15000); + g_assert_cmpint(data.counter, ==, 2); + g_assert_cmpint(data.rs_counter, ==, 1); +} + +static void +test_preference_order_cb(NMNDisc * ndisc, + const NMNDiscData *rdata, + guint changed_int, + TestData * data) +{ + NMNDiscConfigMap changed = changed_int; + + if (data->counter == 1) { + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES + | NM_NDISC_CONFIG_ROUTES); + + g_assert_cmpint(rdata->gateways_n, ==, 2); + match_gateway(rdata, + 0, + "fe80::1", + data->timestamp_msec_1 + 10000, + NM_ICMPV6_ROUTER_PREF_HIGH); + match_gateway(rdata, + 1, + "fe80::2", + data->timestamp_msec_1 + 11000, + NM_ICMPV6_ROUTER_PREF_LOW); + g_assert_cmpint(rdata->addresses_n, ==, 2); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1 + 10000); + match_address(rdata, + 1, + "2001:db8:a:b::1", + data->timestamp_msec_1 + 11000, + data->timestamp_msec_1 + 10000); + g_assert_cmpint(rdata->routes_n, ==, 2); + match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10); + match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 5); + + g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); + g_main_loop_quit(data->loop); + } + + data->counter++; +} + +static void +test_preference_order(void) +{ + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, + }; + guint id; + + /* Test insertion order of gateways */ + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_HIGH); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:a::", + 64, + "fe80::1", + now_msec + 10000, + now_msec + 10000, + 5); + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 11000, NM_ICMPV6_ROUTER_PREF_LOW); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:b::", + 64, + "fe80::2", + now_msec + 11000, + now_msec + 10000, + 10); + + g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_preference_order_cb), &data); + + nm_ndisc_start(NM_NDISC(ndisc)); + nmtst_main_loop_run_assert(data.loop, 15000); + g_assert_cmpint(data.counter, ==, 2); +} + +static void +test_preference_changed_cb(NMNDisc * ndisc, + const NMNDiscData *rdata, + guint changed_int, + TestData * data) +{ + NMNDiscConfigMap changed = changed_int; + + if (data->counter == 1) { + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES + | NM_NDISC_CONFIG_ROUTES); + g_assert_cmpint(rdata->gateways_n, ==, 2); + match_gateway(rdata, + 0, + "fe80::2", + data->timestamp_msec_1 + 11000, + NM_ICMPV6_ROUTER_PREF_MEDIUM); + match_gateway(rdata, + 1, + "fe80::1", + data->timestamp_msec_1 + 10000, + NM_ICMPV6_ROUTER_PREF_LOW); + g_assert_cmpint(rdata->addresses_n, ==, 2); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 10000, + data->timestamp_msec_1 + 10000); + match_address(rdata, + 1, + "2001:db8:a:b::1", + data->timestamp_msec_1 + 11000, + data->timestamp_msec_1 + 11000); + g_assert_cmpint(rdata->routes_n, ==, 2); + match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10); + match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 10000, 5); + } else if (data->counter == 2) { + g_assert_cmpint(changed, + ==, + NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES + | NM_NDISC_CONFIG_ROUTES); + + g_assert_cmpint(rdata->gateways_n, ==, 2); + match_gateway(rdata, + 0, + "fe80::1", + data->timestamp_msec_1 + 12000, + NM_ICMPV6_ROUTER_PREF_HIGH); + match_gateway(rdata, + 1, + "fe80::2", + data->timestamp_msec_1 + 11000, + NM_ICMPV6_ROUTER_PREF_MEDIUM); + g_assert_cmpint(rdata->addresses_n, ==, 2); + match_address(rdata, + 0, + "2001:db8:a:a::1", + data->timestamp_msec_1 + 12000, + data->timestamp_msec_1 + 12000); + match_address(rdata, + 1, + "2001:db8:a:b::1", + data->timestamp_msec_1 + 11000, + data->timestamp_msec_1 + 11000); + g_assert_cmpint(rdata->routes_n, ==, 2); + match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp_msec_1 + 12000, 15); + match_route(rdata, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp_msec_1 + 11000, 10); + + g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); + g_main_loop_quit(data->loop); + } + + data->counter++; +} + +static void +test_preference_changed(void) +{ + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, + }; + guint id; + + /* Test that when a low-preference and medium gateway send advertisements, + * that if the low-preference gateway switches to high-preference, we do + * not get duplicates in the gateway list. + */ + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_LOW); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:a::", + 64, + "fe80::1", + now_msec + 10000, + now_msec + 10000, + 5); + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now_msec + 11000, NM_ICMPV6_ROUTER_PREF_MEDIUM); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:b::", + 64, + "fe80::2", + now_msec + 11000, + now_msec + 11000, + 10); + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 12000, NM_ICMPV6_ROUTER_PREF_HIGH); + nm_fake_ndisc_add_prefix(ndisc, + id, + "2001:db8:a:a::", + 64, + "fe80::1", + now_msec + 12000, + now_msec + 12000, + 15); + + g_signal_connect(ndisc, + NM_NDISC_CONFIG_RECEIVED, + G_CALLBACK(test_preference_changed_cb), + &data); + + nm_ndisc_start(NM_NDISC(ndisc)); + nmtst_main_loop_run_assert(data.loop, 15000); + g_assert_cmpint(data.counter, ==, 3); +} + +/*****************************************************************************/ + +static void +_test_dns_solicit_loop_changed(NMNDisc * ndisc, + const NMNDiscData *rdata, + guint changed_int, + TestData * data) +{ + data->counter++; +} + +static void +_test_dns_solicit_loop_rs_sent(NMFakeNDisc *ndisc, TestData *data) +{ + data->rs_counter++; +} + +static void +test_dns_solicit_loop(void) +{ + nm_auto_unref_gmainloop GMainLoop *loop = g_main_loop_new(NULL, FALSE); + gs_unref_object NMFakeNDisc *ndisc = ndisc_new(); + const gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + TestData data = { + .loop = loop, + .timestamp_msec_1 = now_msec, + }; + guint id; + + /* Ensure that no solicitation loop happens when DNS servers or domains + * stop being sent in advertisements. This can happen if two routers + * send RAs, but the one sending DNS info stops responding, or if one + * router removes the DNS info from the RA without zero-lifetiming them + * first. + */ + + id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); + g_assert(id); + nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now_msec + 10000, NM_ICMPV6_ROUTER_PREF_LOW); + nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now_msec + 6000); + + g_signal_connect(ndisc, + NM_NDISC_CONFIG_RECEIVED, + G_CALLBACK(_test_dns_solicit_loop_changed), + &data); + g_signal_connect(ndisc, + NM_FAKE_NDISC_RS_SENT, + G_CALLBACK(_test_dns_solicit_loop_rs_sent), + &data); + + nm_ndisc_start(NM_NDISC(ndisc)); + if (nmtst_main_loop_run(data.loop, 10000)) + g_error("we expect to run the loop until timeout. What is wrong?"); + g_assert_cmpint(data.counter, ==, 3); + g_assert_cmpint(data.rs_counter, ==, 1); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT"); + + if (nmtst_test_quick()) { + g_print("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", + g_get_prgname() ?: "test-ndisc-fake"); + return g_test_run(); + } + + nm_fake_platform_setup(); + + g_test_add_func("/ndisc/simple", test_simple); + g_test_add_func("/ndisc/everything-changed", test_everything); + g_test_add_func("/ndisc/preference-order", test_preference_order); + g_test_add_func("/ndisc/preference-changed", test_preference_changed); + g_test_add_func("/ndisc/dns-solicit-loop", test_dns_solicit_loop); + + return g_test_run(); +} diff --git a/src/ndisc/tests/test-ndisc-linux.c b/src/core/ndisc/tests/test-ndisc-linux.c index 7e5e258b..9a5df60b 100644 --- a/src/ndisc/tests/test-ndisc-linux.c +++ b/src/core/ndisc/tests/test-ndisc-linux.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <syslog.h> diff --git a/src/nm-act-request.c b/src/core/nm-act-request.c index 67936ca0..defe3e8c 100644 --- a/src/nm-act-request.c +++ b/src/core/nm-act-request.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-act-request.h" @@ -22,14 +22,8 @@ #include "nm-libnm-core-intern/nm-auth-subject.h" typedef struct { - char *table; - char *rule; -} ShareRule; - -typedef struct { - CList call_ids_lst_head; - gboolean shared; - GSList * share_rules; + CList call_ids_lst_head; + NMUtilsShareRules *share_rules; } NMActRequestPrivate; struct _NMActRequest { @@ -254,109 +248,32 @@ nm_act_request_clear_secrets(NMActRequest *self) /*****************************************************************************/ -static void -clear_share_rules(NMActRequest *req) -{ - NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req); - GSList * iter; - - for (iter = priv->share_rules; iter; iter = g_slist_next(iter)) { - ShareRule *rule = (ShareRule *) iter->data; - - g_free(rule->table); - g_free(rule->rule); - g_free(rule); - } - - g_slist_free(priv->share_rules); - priv->share_rules = NULL; -} - -void -nm_act_request_set_shared(NMActRequest *req, gboolean shared) -{ - NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req); - GSList * list, *iter; - - g_return_if_fail(NM_IS_ACT_REQUEST(req)); - - NM_ACT_REQUEST_GET_PRIVATE(req)->shared = shared; - - /* Tear the rules down in reverse order when sharing is stopped */ - list = g_slist_copy(priv->share_rules); - if (!shared) - list = g_slist_reverse(list); - - /* Send the rules to iptables */ - for (iter = list; iter; iter = g_slist_next(iter)) { - ShareRule * rule = (ShareRule *) iter->data; - char * envp[1] = {NULL}; - gs_strfreev char **argv = NULL; - gs_free char * cmd = NULL; - - cmd = g_strdup_printf("%s --table %s %s %s", - IPTABLES_PATH, - rule->table, - shared ? "--insert" : "--delete", - rule->rule); - if (!cmd) - continue; - - argv = g_strsplit(cmd, " ", 0); - if (argv && argv[0]) { - int status; - GError *error = NULL; - - nm_log_info(LOGD_SHARING, "Executing: %s", cmd); - if (!g_spawn_sync("/", - argv, - envp, - G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - NULL, - NULL, - NULL, - NULL, - &status, - &error)) { - nm_log_warn(LOGD_SHARING, "Error executing command: %s", error->message); - g_clear_error(&error); - } else if (WEXITSTATUS(status)) { - nm_log_warn(LOGD_SHARING, - "** Command returned exit status %d.", - WEXITSTATUS(status)); - } - } - } - - g_slist_free(list); - - /* Clear the share rule list when sharing is stopped */ - if (!shared) - clear_share_rules(req); -} - -gboolean +NMUtilsShareRules * nm_act_request_get_shared(NMActRequest *req) { g_return_val_if_fail(NM_IS_ACT_REQUEST(req), FALSE); - return NM_ACT_REQUEST_GET_PRIVATE(req)->shared; + return NM_ACT_REQUEST_GET_PRIVATE(req)->share_rules; } void -nm_act_request_add_share_rule(NMActRequest *req, const char *table, const char *table_rule) +nm_act_request_set_shared(NMActRequest *req, NMUtilsShareRules *rules) { NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE(req); - ShareRule * rule; g_return_if_fail(NM_IS_ACT_REQUEST(req)); - g_return_if_fail(table != NULL); - g_return_if_fail(table_rule != NULL); - rule = g_malloc0(sizeof(ShareRule)); - rule->table = g_strdup(table); - rule->rule = g_strdup(table_rule); - priv->share_rules = g_slist_prepend(priv->share_rules, rule); + if (priv->share_rules == rules) + return; + + if (priv->share_rules) { + nm_utils_share_rules_apply(priv->share_rules, FALSE); + priv->share_rules = NULL; + } + if (rules) { + priv->share_rules = rules; + nm_utils_share_rules_apply(priv->share_rules, TRUE); + } } /*****************************************************************************/ @@ -558,24 +475,24 @@ nm_act_request_new(NMSettingsConnection * settings_connection, g_return_val_if_fail(NM_IS_DEVICE(device), NULL); g_return_val_if_fail(NM_IS_AUTH_SUBJECT(subject), NULL); - return (NMActRequest *) g_object_new(NM_TYPE_ACT_REQUEST, - NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, - applied_connection, - NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, - settings_connection, - NM_ACTIVE_CONNECTION_INT_DEVICE, - device, - NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, - specific_object, - NM_ACTIVE_CONNECTION_INT_SUBJECT, - subject, - NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, - (int) activation_type, - NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, - (int) activation_reason, - NM_ACTIVE_CONNECTION_STATE_FLAGS, - (guint) initial_state_flags, - NULL); + return g_object_new(NM_TYPE_ACT_REQUEST, + NM_ACTIVE_CONNECTION_INT_APPLIED_CONNECTION, + applied_connection, + NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, + settings_connection, + NM_ACTIVE_CONNECTION_INT_DEVICE, + device, + NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, + specific_object, + NM_ACTIVE_CONNECTION_INT_SUBJECT, + subject, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_TYPE, + (int) activation_type, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, + (int) activation_reason, + NM_ACTIVE_CONNECTION_STATE_FLAGS, + (guint) initial_state_flags, + NULL); } static void @@ -589,10 +506,9 @@ 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); - /* Clear any share rules */ if (priv->share_rules) { - nm_act_request_set_shared(NM_ACT_REQUEST(object), FALSE); - clear_share_rules(NM_ACT_REQUEST(object)); + nm_utils_share_rules_apply(priv->share_rules, FALSE); + nm_clear_pointer(&priv->share_rules, nm_utils_share_rules_free); } G_OBJECT_CLASS(nm_act_request_parent_class)->dispose(object); diff --git a/src/nm-act-request.h b/src/core/nm-act-request.h index 65c8abf5..2a568430 100644 --- a/src/nm-act-request.h +++ b/src/core/nm-act-request.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2012 Red Hat, Inc. */ @@ -36,11 +36,15 @@ NMSettingsConnection *nm_act_request_get_settings_connection(NMActRequest *req); NMConnection *nm_act_request_get_applied_connection(NMActRequest *req); -gboolean nm_act_request_get_shared(NMActRequest *req); +/*****************************************************************************/ -void nm_act_request_set_shared(NMActRequest *req, gboolean shared); +struct _NMUtilsShareRules; -void nm_act_request_add_share_rule(NMActRequest *req, const char *table, const char *rule); +struct _NMUtilsShareRules *nm_act_request_get_shared(NMActRequest *req); + +void nm_act_request_set_shared(NMActRequest *req, struct _NMUtilsShareRules *rules); + +/*****************************************************************************/ /* Secrets handling */ diff --git a/src/nm-active-connection.c b/src/core/nm-active-connection.c index a8b8e2f3..3c8c472e 100644 --- a/src/nm-active-connection.c +++ b/src/core/nm-active-connection.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-active-connection.h" diff --git a/src/nm-active-connection.h b/src/core/nm-active-connection.h index 9c39835d..15c68e6e 100644 --- a/src/nm-active-connection.h +++ b/src/core/nm-active-connection.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2012 Red Hat, Inc. */ diff --git a/src/nm-audit-manager.c b/src/core/nm-audit-manager.c index 527a3904..8f419472 100644 --- a/src/nm-audit-manager.c +++ b/src/core/nm-audit-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-audit-manager.h" diff --git a/src/nm-audit-manager.h b/src/core/nm-audit-manager.h index 65076513..fdabbf28 100644 --- a/src/nm-audit-manager.h +++ b/src/core/nm-audit-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ diff --git a/src/nm-auth-manager.c b/src/core/nm-auth-manager.c index 1cb4834a..9470838c 100644 --- a/src/nm-auth-manager.c +++ b/src/core/nm-auth-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-auth-manager.h" diff --git a/src/nm-auth-manager.h b/src/core/nm-auth-manager.h index 8dc821df..991083c1 100644 --- a/src/nm-auth-manager.h +++ b/src/core/nm-auth-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/nm-auth-utils.c b/src/core/nm-auth-utils.c index b4bbd824..12da5749 100644 --- a/src/nm-auth-utils.c +++ b/src/core/nm-auth-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-auth-utils.h" diff --git a/src/nm-auth-utils.h b/src/core/nm-auth-utils.h index 309c5b51..999dacf5 100644 --- a/src/nm-auth-utils.h +++ b/src/core/nm-auth-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ diff --git a/src/nm-checkpoint-manager.c b/src/core/nm-checkpoint-manager.c index 5d36213b..b8c9101a 100644 --- a/src/nm-checkpoint-manager.c +++ b/src/core/nm-checkpoint-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-checkpoint-manager.h" diff --git a/src/nm-checkpoint-manager.h b/src/core/nm-checkpoint-manager.h index 051cfd52..7fe86d60 100644 --- a/src/nm-checkpoint-manager.h +++ b/src/core/nm-checkpoint-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/nm-checkpoint.c b/src/core/nm-checkpoint.c index b26f7e80..2088c247 100644 --- a/src/nm-checkpoint.c +++ b/src/core/nm-checkpoint.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-checkpoint.h" diff --git a/src/nm-checkpoint.h b/src/core/nm-checkpoint.h index 7e2fff59..28c936fa 100644 --- a/src/nm-checkpoint.h +++ b/src/core/nm-checkpoint.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/nm-config-data.c b/src/core/nm-config-data.c index 4320e26b..c62c6773 100644 --- a/src/nm-config-data.c +++ b/src/core/nm-config-data.c @@ -1,18 +1,18 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-config-data.h" #include "nm-config.h" #include "devices/nm-device.h" #include "nm-core-internal.h" -#include "nm-keyfile/nm-keyfile-internal.h" -#include "nm-keyfile/nm-keyfile-utils.h" +#include "nm-keyfile-internal.h" +#include "nm-keyfile-utils.h" /*****************************************************************************/ @@ -1345,8 +1345,8 @@ global_dns_equal(NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) if (!old || !new) return FALSE; - if (!_nm_utils_strv_equal(old->options, new->options) - || !_nm_utils_strv_equal(old->searches, new->searches)) + if (!nm_utils_strv_equal(old->options, new->options) + || !nm_utils_strv_equal(old->searches, new->searches)) return FALSE; if ((!old->domains || !new->domains) && old->domains != new->domains) @@ -1364,8 +1364,8 @@ global_dns_equal(NMGlobalDnsConfig *old, NMGlobalDnsConfig *new) domain_old = value_old; domain_new = value_new; - if (!_nm_utils_strv_equal(domain_old->options, domain_new->options) - || !_nm_utils_strv_equal(domain_old->servers, domain_new->servers)) + if (!nm_utils_strv_equal(domain_old->options, domain_new->options) + || !nm_utils_strv_equal(domain_old->servers, domain_new->servers)) return FALSE; } diff --git a/src/nm-config-data.h b/src/core/nm-config-data.h index c15e6642..07cffb43 100644 --- a/src/nm-config-data.h +++ b/src/core/nm-config-data.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ diff --git a/src/nm-config.c b/src/core/nm-config.c index 8f46661d..55323919 100644 --- a/src/nm-config.c +++ b/src/core/nm-config.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-config.h" @@ -14,8 +14,8 @@ #include "devices/nm-device.h" #include "NetworkManagerUtils.h" #include "nm-core-internal.h" -#include "nm-keyfile/nm-keyfile-internal.h" -#include "nm-keyfile/nm-keyfile-utils.h" +#include "nm-keyfile-internal.h" +#include "nm-keyfile-utils.h" #define DEFAULT_CONFIG_MAIN_FILE NMCONFDIR "/NetworkManager.conf" #define DEFAULT_CONFIG_DIR NMCONFDIR "/conf.d" @@ -885,6 +885,7 @@ static const ConfigGroup config_groups[] = { NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_BACKEND, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_RAND_MAC_ADDRESS, NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_GENERATE_MAC_ADDRESS_MASK, + NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_IWD_AUTOCONNECT, NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE, NM_CONFIG_KEYFILE_KEY_STOP_MATCH, ), }, diff --git a/src/nm-config.h b/src/core/nm-config.h index 9f866f29..6f3f514c 100644 --- a/src/nm-config.h +++ b/src/core/nm-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2013 Thomas Bechtold <thomasbechtold@jpberlin.de> @@ -88,6 +88,7 @@ #define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_SCAN_GENERATE_MAC_ADDRESS_MASK \ "wifi.scan-generate-mac-address-mask" #define NM_CONFIG_KEYFILE_KEY_DEVICE_CARRIER_WAIT_TIMEOUT "carrier-wait-timeout" +#define NM_CONFIG_KEYFILE_KEY_DEVICE_WIFI_IWD_AUTOCONNECT "wifi.iwd.autoconnect" #define NM_CONFIG_KEYFILE_KEY_MATCH_DEVICE "match-device" #define NM_CONFIG_KEYFILE_KEY_STOP_MATCH "stop-match" diff --git a/src/nm-connectivity.c b/src/core/nm-connectivity.c index 3cd1d4b8..f847c8f4 100644 --- a/src/nm-connectivity.c +++ b/src/core/nm-connectivity.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de> * Copyright (C) 2011 Dan Williams <dcbw@redhat.com> * Copyright (C) 2016 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-connectivity.h" diff --git a/src/nm-connectivity.h b/src/core/nm-connectivity.h index 620eff35..c67668ce 100644 --- a/src/nm-connectivity.h +++ b/src/core/nm-connectivity.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Thomas Bechtold <thomasbechtold@jpberlin.de> * Copyright (C) 2017 Red Hat, Inc. diff --git a/src/nm-core-utils.c b/src/core/nm-core-utils.c index 7adc011e..9075c30d 100644 --- a/src/nm-core-utils.c +++ b/src/core/nm-core-utils.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2018 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-core-utils.h" @@ -187,51 +187,46 @@ nm_utils_exp10(gint16 ex) /*****************************************************************************/ -/* - * nm_ethernet_address_is_valid: - * @addr: pointer to a binary or ASCII Ethernet address - * @len: length of @addr, or -1 if @addr is ASCII - * - * Compares an Ethernet address against known invalid addresses. - - * Returns: %TRUE if @addr is a valid Ethernet address, %FALSE if it is not. - */ gboolean -nm_ethernet_address_is_valid(gconstpointer addr, gssize len) +nm_ether_addr_is_valid(const NMEtherAddr *addr) { - guint8 invalid_addr[4][ETH_ALEN] = { + static const guint8 invalid_addr[][ETH_ALEN] = { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x44, 0x44, 0x44, 0x44, 0x44, 0x44}, {0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}, /* prism54 dummy MAC */ }; - guint8 addr_bin[ETH_ALEN]; - guint i; + int i; - if (!addr) { - g_return_val_if_fail(len == -1 || len == ETH_ALEN, FALSE); + if (!addr) return FALSE; - } - - if (len == -1) { - if (!nm_utils_hwaddr_aton(addr, addr_bin, ETH_ALEN)) - return FALSE; - addr = addr_bin; - } else if (len != ETH_ALEN) - g_return_val_if_reached(FALSE); /* Check for multicast address */ - if ((((guint8 *) addr)[0]) & 0x01) + if (addr->ether_addr_octet[0] & 0x01u) return FALSE; - for (i = 0; i < G_N_ELEMENTS(invalid_addr); i++) { - if (nm_utils_hwaddr_matches(addr, ETH_ALEN, invalid_addr[i], ETH_ALEN)) + for (i = 0; i < (int) G_N_ELEMENTS(invalid_addr); i++) { + if (memcmp(addr, invalid_addr[i], ETH_ALEN) == 0) return FALSE; } return TRUE; } +gboolean +nm_ether_addr_is_valid_str(const char *str) +{ + NMEtherAddr addr_bin; + + if (!str) + return FALSE; + + if (!nm_utils_hwaddr_aton(str, &addr_bin, ETH_ALEN)) + return FALSE; + + return nm_ether_addr_is_valid(&addr_bin); +} + /*****************************************************************************/ void @@ -4040,6 +4035,30 @@ nm_utils_create_dhcp_iaid(gboolean legacy_unstable_byteorder, } } +GBytes * +nm_utils_dhcp_client_id_duid(guint32 iaid, const guint8 *duid, gsize duid_len) +{ + struct _nm_packed { + guint8 type; + guint32 iaid; + guint8 duid[]; + } * client_id; + gsize total_size; + + /* the @duid must include the 16 bit duid-type and the data (of max 128 bytes). */ + g_return_val_if_fail(duid_len > 2 && duid_len < 128 + 2, NULL); + g_return_val_if_fail(duid, NULL); + + total_size = sizeof(*client_id) + duid_len; + + client_id = g_malloc(total_size); + + client_id->type = 255; + unaligned_write_be32(&client_id->iaid, iaid); + memcpy(client_id->duid, duid, duid_len); + return g_bytes_new_take(client_id, total_size); +} + /** * nm_utils_dhcp_client_id_systemd_node_specific_full: * @iaid: the IAID (identity association identifier) in native byte order @@ -4250,29 +4269,6 @@ nm_utils_g_value_set_strv(GValue *value, GPtrArray *strings) /*****************************************************************************/ -void -nm_utils_ifname_cpy(char *dst, const char *name) -{ - int i; - - g_return_if_fail(dst); - g_return_if_fail(name && name[0]); - - nm_assert(nm_utils_ifname_valid_kernel(name, NULL)); - - /* ensures NUL padding of the entire IFNAMSIZ buffer. */ - - for (i = 0; i < (int) IFNAMSIZ && name[i] != '\0'; i++) - dst[i] = name[i]; - - nm_assert(name[i] == '\0'); - - for (; i < (int) IFNAMSIZ; i++) - dst[i] = '\0'; -} - -/*****************************************************************************/ - /** * Takes a pair @timestamp and @duration, and returns the remaining duration based * on the new timestamp @now. @@ -4386,7 +4382,7 @@ nm_utils_dnsmasq_status_to_string(int status, char *dest, gsize size) } /** - * nm_utils_get_reverse_dns_domains_ip4: + * nm_utils_get_reverse_dns_domains_ip_4: * @addr: IP address in network order * @plen: prefix length * @domains: array for results @@ -4395,7 +4391,7 @@ nm_utils_dnsmasq_status_to_string(int status, char *dest, gsize size) * append them to @domains. */ void -nm_utils_get_reverse_dns_domains_ip4(guint32 addr, guint8 plen, GPtrArray *domains) +nm_utils_get_reverse_dns_domains_ip_4(guint32 addr, guint8 plen, GPtrArray *domains) { guint32 ip, ip2, mask; guchar *p; @@ -4434,7 +4430,7 @@ nm_utils_get_reverse_dns_domains_ip4(guint32 addr, guint8 plen, GPtrArray *domai } /** - * nm_utils_get_reverse_dns_domains_ip6: + * nm_utils_get_reverse_dns_domains_ip_6: * @addr: IPv6 address * @plen: prefix length * @domains: array for results @@ -4443,7 +4439,7 @@ nm_utils_get_reverse_dns_domains_ip4(guint32 addr, guint8 plen, GPtrArray *domai * append them to @domains. */ void -nm_utils_get_reverse_dns_domains_ip6(const struct in6_addr *ip, guint8 plen, GPtrArray *domains) +nm_utils_get_reverse_dns_domains_ip_6(const struct in6_addr *ip, guint8 plen, GPtrArray *domains) { struct in6_addr addr; guint nibbles, bits, entries; diff --git a/src/nm-core-utils.h b/src/core/nm-core-utils.h index 237574c5..5dc4d432 100644 --- a/src/nm-core-utils.h +++ b/src/core/nm-core-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2016 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. @@ -54,7 +54,7 @@ void _nm_singleton_instance_register_destruction(GObject *instance); if (G_UNLIKELY(!singleton_instance)) { \ g_assert(!(_already_created_##GETTER) || (NM_DEFINE_SINGLETON_ALLOW_MULTIPLE)); \ (_already_created_##GETTER) = TRUE; \ - singleton_instance = (g_object_new(GTYPE, ##__VA_ARGS__, NULL)); \ + singleton_instance = g_object_new(GTYPE, ##__VA_ARGS__, NULL); \ g_assert(singleton_instance); \ nm_singleton_instance_register(); \ nm_log_dbg(LOGD_CORE, \ @@ -95,7 +95,8 @@ void _nm_singleton_instance_register_destruction(GObject *instance); /*****************************************************************************/ -gboolean nm_ethernet_address_is_valid(gconstpointer addr, gssize len); +gboolean nm_ether_addr_is_valid(const NMEtherAddr *addr); +gboolean nm_ether_addr_is_valid_str(const char *str); gconstpointer nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint8 plen); @@ -209,7 +210,7 @@ nm_utils_ip6_route_metric_normalize(guint32 metric) static inline guint32 nm_utils_ip_route_metric_normalize(int addr_family, guint32 metric) { - return addr_family == AF_INET6 ? nm_utils_ip6_route_metric_normalize(metric) : metric; + return NM_IS_IPv4(addr_family) ? metric : nm_utils_ip6_route_metric_normalize(metric); } static inline guint32 @@ -448,6 +449,8 @@ guint32 nm_utils_create_dhcp_iaid(gboolean legacy_unstable_byteorder, const guint8 *interface_id, gsize interface_id_len); +GBytes *nm_utils_dhcp_client_id_duid(guint32 iaid, const guint8 *duid, gsize duid_len); + GBytes *nm_utils_dhcp_client_id_systemd_node_specific_full(guint32 iaid, const guint8 *machine_id, gsize machine_id_len); @@ -498,8 +501,6 @@ void _nm_utils_set_testing(NMUtilsTestFlags flags); void nm_utils_g_value_set_strv(GValue *value, GPtrArray *strings); -void nm_utils_ifname_cpy(char *dst, const char *name); - guint32 nm_utils_lifetime_rebase_relative_time_on_now(guint32 timestamp, guint32 duration, gint32 now); @@ -531,9 +532,21 @@ nm_utils_ip4_address_is_zeronet(in_addr_t network) const char *nm_utils_dnsmasq_status_to_string(int status, char *dest, gsize size); -void nm_utils_get_reverse_dns_domains_ip4(guint32 ip, guint8 plen, GPtrArray *domains); +void nm_utils_get_reverse_dns_domains_ip_4(guint32 ip, guint8 plen, GPtrArray *domains); void -nm_utils_get_reverse_dns_domains_ip6(const struct in6_addr *ip, guint8 plen, GPtrArray *domains); +nm_utils_get_reverse_dns_domains_ip_6(const struct in6_addr *ip, guint8 plen, GPtrArray *domains); + +static inline void +nm_utils_get_reverse_dns_domains_ip(int addr_family, + gconstpointer addr, + guint8 plen, + GPtrArray * domains) +{ + if (NM_IS_IPv4(addr_family)) + nm_utils_get_reverse_dns_domains_ip_4(*((const in_addr_t *) addr), plen, domains); + else + nm_utils_get_reverse_dns_domains_ip_6(addr, plen, domains); +} struct stat; @@ -546,7 +559,7 @@ char * nm_utils_format_con_diff_for_audit(GHashTable *diff); /* this enum is compatible with ICMPV6_ROUTER_PREF_* (from <linux/icmpv6.h>, * the values for netlink attribute RTA_PREF) and "enum ndp_route_preference" * from <ndp.h>. */ -typedef enum { +typedef enum _nm_packed { NM_ICMPV6_ROUTER_PREF_MEDIUM = 0x0, /* ICMPV6_ROUTER_PREF_MEDIUM */ NM_ICMPV6_ROUTER_PREF_LOW = 0x3, /* ICMPV6_ROUTER_PREF_LOW */ NM_ICMPV6_ROUTER_PREF_HIGH = 0x1, /* ICMPV6_ROUTER_PREF_HIGH */ diff --git a/src/nm-dbus-manager.c b/src/core/nm-dbus-manager.c index 00cb6a9f..4f34ee52 100644 --- a/src/nm-dbus-manager.c +++ b/src/core/nm-dbus-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dbus-manager.h" diff --git a/src/nm-dbus-manager.h b/src/core/nm-dbus-manager.h index 5d20e0d5..06876af0 100644 --- a/src/nm-dbus-manager.h +++ b/src/core/nm-dbus-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2008 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/nm-dbus-object.c b/src/core/nm-dbus-object.c index f49610ab..6f294fe2 100644 --- a/src/nm-dbus-object.c +++ b/src/core/nm-dbus-object.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dbus-object.h" diff --git a/src/nm-dbus-object.h b/src/core/nm-dbus-object.h index e7deef53..d94bd5df 100644 --- a/src/nm-dbus-object.h +++ b/src/core/nm-dbus-object.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/nm-dbus-utils.c b/src/core/nm-dbus-utils.c index d5e8cb3a..5890bdf2 100644 --- a/src/nm-dbus-utils.c +++ b/src/core/nm-dbus-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dbus-utils.h" diff --git a/src/nm-dbus-utils.h b/src/core/nm-dbus-utils.h index 48177973..501e1996 100644 --- a/src/nm-dbus-utils.h +++ b/src/core/nm-dbus-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/nm-dcb.c b/src/core/nm-dcb.c index d7c047b3..b3958caa 100644 --- a/src/nm-dcb.c +++ b/src/core/nm-dcb.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <sys/wait.h> diff --git a/src/nm-dcb.h b/src/core/nm-dcb.h index 3024c30a..7cb5e7ef 100644 --- a/src/nm-dcb.h +++ b/src/core/nm-dcb.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/core/nm-default-daemon.h b/src/core/nm-default-daemon.h new file mode 100644 index 00000000..65ca4b54 --- /dev/null +++ b/src/core/nm-default-daemon.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEFAULT_DAEMON_H__ +#define __NM_DEFAULT_DAEMON_H__ + +/*****************************************************************************/ + +#include "nm-glib-aux/nm-default-glib-i18n-prog.h" + +#undef NETWORKMANAGER_COMPILATION +#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_DAEMON + +/*****************************************************************************/ + +#include "nm-version.h" + +#include "nm-core-types.h" +#include "nm-types.h" +#include "nm-log-core/nm-logging.h" + +/*****************************************************************************/ + +#endif /* __NM_DEFAULT_DAEMON_H__ */ diff --git a/src/nm-dhcp-config.c b/src/core/nm-dhcp-config.c index 3788e4f3..718d3c90 100644 --- a/src/nm-dhcp-config.c +++ b/src/core/nm-dhcp-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dhcp-config.h" diff --git a/src/nm-dhcp-config.h b/src/core/nm-dhcp-config.h index dbd0b5e7..9e68f2fb 100644 --- a/src/nm-dhcp-config.h +++ b/src/core/nm-dhcp-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/nm-dispatcher.c b/src/core/nm-dispatcher.c index feab265d..0ab409f5 100644 --- a/src/nm-dispatcher.c +++ b/src/core/nm-dispatcher.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2018 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dispatcher.h" @@ -167,140 +167,131 @@ dump_proxy_to_props(NMProxyConfig *proxy, GVariantBuilder *builder) } static void -dump_ip4_to_props(NMIP4Config *ip4, GVariantBuilder *builder) +dump_ip_to_props(NMIPConfig *ip, GVariantBuilder *builder) { - GVariantBuilder int_builder; - NMDedupMultiIter ipconf_iter; - gboolean first; - guint n, i; - const NMPlatformIP4Address *addr; - const NMPlatformIP4Route * route; - guint32 array[4]; - - /* Addresses */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau")); - first = TRUE; - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, ip4, &addr) { - const NMPObject *default_route; - - array[0] = addr->address; - array[1] = addr->plen; - array[2] = (first && (default_route = nm_ip4_config_best_default_route_get(ip4))) - ? NMP_OBJECT_CAST_IP4_ROUTE(default_route)->gateway - : (guint32) 0; - g_variant_builder_add( - &int_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 3, sizeof(guint32))); - first = FALSE; + 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; + + 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))) { + const NMPlatformIPXAddress *addr = NMP_OBJECT_CAST_IPX_ADDRESS(obj); + + if (IS_IPv4) { + guint32 array[3]; + in_addr_t gw; + + gw = 0u; + if (default_route) { + gw = NMP_OBJECT_CAST_IP4_ROUTE(default_route)->gateway; + default_route = NULL; + } + array[0] = addr->a4.address; + array[1] = addr->a4.plen; + array[2] = gw; + g_variant_builder_add( + &int_builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 3, sizeof(guint32))); + } else { + const struct in6_addr *gw = &in6addr_any; + + if (default_route) { + gw = &NMP_OBJECT_CAST_IP6_ROUTE(default_route)->gateway; + default_route = NULL; + } + var1 = nm_g_variant_new_ay_in6addr(&addr->a6.address); + var2 = nm_g_variant_new_ay_in6addr(gw); + g_variant_builder_add(&int_builder, "(@ayu@ay)", var1, addr->a6.plen, var2); + } } g_variant_builder_add(builder, "{sv}", "addresses", g_variant_builder_end(&int_builder)); - /* DNS servers */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au")); - n = nm_ip4_config_get_num_nameservers(ip4); - for (i = 0; i < n; i++) - g_variant_builder_add(&int_builder, "u", nm_ip4_config_get_nameserver(ip4, i)); + if (IS_IPv4) + 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); + 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)); + g_variant_builder_add(&int_builder, "@ay", var1); + } + } g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder)); - /* Search domains */ g_variant_builder_init(&int_builder, G_VARIANT_TYPE("as")); - n = nm_ip4_config_get_num_domains(ip4); + n = nm_ip_config_get_num_domains(ip); for (i = 0; i < n; i++) - g_variant_builder_add(&int_builder, "s", nm_ip4_config_get_domain(ip4, i)); + g_variant_builder_add(&int_builder, "s", nm_ip_config_get_domain(ip, i)); g_variant_builder_add(builder, "{sv}", "domains", g_variant_builder_end(&int_builder)); - /* WINS servers */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au")); - n = nm_ip4_config_get_num_wins(ip4); - for (i = 0; i < n; i++) - g_variant_builder_add(&int_builder, "u", nm_ip4_config_get_wins(ip4, i)); - g_variant_builder_add(builder, "{sv}", "wins-servers", g_variant_builder_end(&int_builder)); - - /* Static routes */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aau")); - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, ip4, &route) { - if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) - continue; - array[0] = route->network; - array[1] = route->plen; - array[2] = route->gateway; - array[3] = route->metric; - g_variant_builder_add( - &int_builder, - "@au", - g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 4, sizeof(guint32))); + if (IS_IPv4) { + g_variant_builder_init(&int_builder, G_VARIANT_TYPE("au")); + n = nm_ip4_config_get_num_wins(NM_IP4_CONFIG(ip)); + 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(builder, "{sv}", "wins-servers", g_variant_builder_end(&int_builder)); } - g_variant_builder_add(builder, "{sv}", "routes", g_variant_builder_end(&int_builder)); -} -static void -dump_ip6_to_props(NMIP6Config *ip6, GVariantBuilder *builder) -{ - GVariantBuilder int_builder; - NMDedupMultiIter ipconf_iter; - guint n, i; - gboolean first; - const NMPlatformIP6Address *addr; - const NMPlatformIP6Route * route; - GVariant * ip, *gw; - - /* Addresses */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuay)")); - - first = TRUE; - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, ip6, &addr) { - const NMPObject *default_route; - - ip = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - &addr->address, - sizeof(struct in6_addr), - 1); - gw = g_variant_new_fixed_array( - G_VARIANT_TYPE_BYTE, - (first && (default_route = nm_ip6_config_best_default_route_get(ip6))) - ? &NMP_OBJECT_CAST_IP6_ROUTE(default_route)->gateway - : &in6addr_any, - sizeof(struct in6_addr), - 1); - g_variant_builder_add(&int_builder, "(@ayu@ay)", ip, addr->plen, gw); - first = FALSE; - } - g_variant_builder_add(builder, "{sv}", "addresses", g_variant_builder_end(&int_builder)); - - /* DNS servers */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("aay")); - n = nm_ip6_config_get_num_nameservers(ip6); - for (i = 0; i < n; i++) { - ip = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - nm_ip6_config_get_nameserver(ip6, i), - sizeof(struct in6_addr), - 1); - g_variant_builder_add(&int_builder, "@ay", ip); - } - g_variant_builder_add(builder, "{sv}", "nameservers", g_variant_builder_end(&int_builder)); - - /* Search domains */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("as")); - n = nm_ip6_config_get_num_domains(ip6); - for (i = 0; i < n; i++) - g_variant_builder_add(&int_builder, "s", nm_ip6_config_get_domain(ip6, 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("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))) { + const NMPlatformIPXRoute *route = NMP_OBJECT_CAST_IPX_ROUTE(obj); - /* Static routes */ - g_variant_builder_init(&int_builder, G_VARIANT_TYPE("a(ayuayu)")); - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, ip6, &route) { if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(route)) continue; - ip = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - &route->network, - sizeof(struct in6_addr), - 1); - gw = g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, - &route->gateway, - sizeof(struct in6_addr), - 1); - g_variant_builder_add(&int_builder, "(@ayu@ayu)", ip, route->plen, gw, route->metric); + + if (IS_IPv4) { + guint32 array[4]; + + array[0] = route->r4.network; + array[1] = route->r4.plen; + array[2] = route->r4.gateway; + array[3] = route->r4.metric; + g_variant_builder_add( + &int_builder, + "@au", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, array, 4, sizeof(guint32))); + } else { + var1 = nm_g_variant_new_ay_in6addr(&route->r6.network); + var2 = nm_g_variant_new_ay_in6addr(&route->r6.gateway); + g_variant_builder_add(&int_builder, + "(@ayu@ayu)", + var1, + route->r6.plen, + var2, + route->r6.metric); + } } g_variant_builder_add(builder, "{sv}", "routes", g_variant_builder_end(&int_builder)); } @@ -350,11 +341,11 @@ fill_device_props(NMDevice * device, ip4_config = nm_device_get_ip4_config(device); if (ip4_config) - dump_ip4_to_props(ip4_config, ip4_builder); + dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder); ip6_config = nm_device_get_ip6_config(device); if (ip6_config) - dump_ip6_to_props(ip6_config, ip6_builder); + dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder); dhcp_config = nm_device_get_dhcp_config(device, AF_INET); if (dhcp_config) @@ -376,9 +367,9 @@ fill_vpn_props(NMProxyConfig * proxy_config, if (proxy_config) dump_proxy_to_props(proxy_config, proxy_builder); if (ip4_config) - dump_ip4_to_props(ip4_config, ip4_builder); + dump_ip_to_props(NM_IP_CONFIG(ip4_config), ip4_builder); if (ip6_config) - dump_ip6_to_props(ip6_config, ip6_builder); + dump_ip_to_props(NM_IP_CONFIG(ip6_config), ip6_builder); } static const char * diff --git a/src/nm-dispatcher.h b/src/core/nm-dispatcher.h index 202f44b0..d588de4e 100644 --- a/src/nm-dispatcher.h +++ b/src/core/nm-dispatcher.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. diff --git a/src/nm-firewall-manager.c b/src/core/nm-firewall-manager.c index 7ae9ee89..8f476e51 100644 --- a/src/nm-firewall-manager.c +++ b/src/core/nm-firewall-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-firewall-manager.h" diff --git a/src/nm-firewall-manager.h b/src/core/nm-firewall-manager.h index 3b165854..1ce802b2 100644 --- a/src/nm-firewall-manager.h +++ b/src/core/nm-firewall-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Red Hat, Inc. */ diff --git a/src/nm-hostname-manager.c b/src/core/nm-hostname-manager.c index 413b756a..c99c8326 100644 --- a/src/nm-hostname-manager.c +++ b/src/core/nm-hostname-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-hostname-manager.h" diff --git a/src/nm-hostname-manager.h b/src/core/nm-hostname-manager.h index f88501f0..0fa13771 100644 --- a/src/nm-hostname-manager.h +++ b/src/core/nm-hostname-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> diff --git a/src/nm-iface-helper.c b/src/core/nm-iface-helper.c index e5d85967..b6e9981d 100644 --- a/src/nm-iface-helper.c +++ b/src/core/nm-iface-helper.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <glib-unix.h> #include <getopt.h> @@ -21,7 +21,7 @@ #include "main-utils.h" #include "NetworkManagerUtils.h" #include "platform/nm-linux-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "dhcp/nm-dhcp-manager.h" #include "ndisc/nm-ndisc.h" #include "ndisc/nm-lndp-ndisc.h" diff --git a/src/nm-ip-config.c b/src/core/nm-ip-config.c index d9bbf850..2426eb49 100644 --- a/src/nm-ip-config.c +++ b/src/core/nm-ip-config.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ip-config.h" diff --git a/src/nm-ip-config.h b/src/core/nm-ip-config.h index d5f4e5a4..8e1a5934 100644 --- a/src/nm-ip-config.h +++ b/src/core/nm-ip-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2013 Red Hat, Inc. */ diff --git a/src/nm-ip4-config.c b/src/core/nm-ip4-config.c index 9d2b459d..c49dfb4c 100644 --- a/src/nm-ip4-config.c +++ b/src/core/nm-ip4-config.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ip4-config.h" @@ -17,7 +17,7 @@ #include "nm-utils.h" #include "platform/nmp-object.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "NetworkManagerUtils.h" #include "nm-core-internal.h" #include "nm-dbus-object.h" @@ -365,7 +365,8 @@ nm_ip4_config_lookup_addresses(const NMIP4Config *self) void nm_ip_config_iter_ip4_address_init(NMDedupMultiIter *ipconf_iter, const NMIP4Config *self) { - g_return_if_fail(NM_IS_IP4_CONFIG(self)); + nm_assert(NM_IS_IP4_CONFIG(self)); + nm_dedup_multi_iter_init(ipconf_iter, nm_ip4_config_lookup_addresses(self)); } @@ -383,6 +384,7 @@ 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)); } @@ -3120,12 +3122,12 @@ NMIP4Config * nm_ip4_config_new(NMDedupMultiIndex *multi_idx, int ifindex) { g_return_val_if_fail(ifindex >= -1, NULL); - return (NMIP4Config *) g_object_new(NM_TYPE_IP4_CONFIG, - NM_IP4_CONFIG_MULTI_IDX, - multi_idx, - NM_IP4_CONFIG_IFINDEX, - ifindex, - NULL); + return g_object_new(NM_TYPE_IP4_CONFIG, + NM_IP4_CONFIG_MULTI_IDX, + multi_idx, + NM_IP4_CONFIG_IFINDEX, + ifindex, + NULL); } static void diff --git a/src/nm-ip4-config.h b/src/core/nm-ip4-config.h index ccfca74c..a795e152 100644 --- a/src/nm-ip4-config.h +++ b/src/core/nm-ip4-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2013 Red Hat, Inc. */ @@ -319,14 +319,21 @@ NM_IS_IP_CONFIG_ADDR_FAMILY(gconstpointer config, int addr_family) 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) { - if (NM_IS_IP4_CONFIG(config)) - return AF_INET; - if (NM_IS_IP6_CONFIG(config)) - return AF_INET6; - g_return_val_if_reached(AF_UNSPEC); + return nm_ip_config_is_ipv4(config) ? AF_INET : AF_INET6; } #define _NM_IP_CONFIG_DISPATCH(config, v4_func, v6_func, ...) \ @@ -334,10 +341,9 @@ nm_ip_config_get_addr_family(const NMIPConfig *config) { \ gconstpointer _config = (config); \ \ - if (NM_IS_IP4_CONFIG(_config)) { \ + if (nm_ip_config_is_ipv4(_config)) { \ return v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \ } else { \ - nm_assert(NM_IS_IP6_CONFIG(_config)); \ return v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \ } \ } \ @@ -348,10 +354,9 @@ nm_ip_config_get_addr_family(const NMIPConfig *config) { \ gconstpointer _config = (config); \ \ - if (NM_IS_IP4_CONFIG(_config)) { \ + if (nm_ip_config_is_ipv4(_config)) { \ v4_func((NMIP4Config *) _config, ##__VA_ARGS__); \ } else { \ - nm_assert(NM_IS_IP6_CONFIG(_config)); \ v6_func((NMIP6Config *) _config, ##__VA_ARGS__); \ } \ } \ @@ -369,6 +374,38 @@ 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) { @@ -543,11 +580,9 @@ nm_ip_config_set_never_default(NMIPConfig *self, gboolean never_default) gpointer _dst = (dst); \ gconstpointer _src = (src); \ \ - if (NM_IS_IP4_CONFIG(_dst)) { \ - nm_assert(NM_IS_IP4_CONFIG(_src)); \ + if (nm_ip_config_is_ipv4(_dst)) { \ _return v4_func((NMIP4Config *) _dst, (const NMIP4Config *) _src, ##__VA_ARGS__); \ } else { \ - nm_assert(NM_IS_IP6_CONFIG(_src)); \ _return v6_func((NMIP6Config *) _dst, (const NMIP6Config *) _src, ##__VA_ARGS__); \ } \ } \ @@ -610,7 +645,8 @@ nm_ip_config_intersect_alloc(const NMIPConfig *a, gboolean intersect_routes, guint32 default_route_metric_penalty) { - if (NM_IS_IP4_CONFIG(a)) { + 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, diff --git a/src/nm-ip6-config.c b/src/core/nm-ip6-config.c index 407aa1d6..1f7def34 100644 --- a/src/nm-ip6-config.c +++ b/src/core/nm-ip6-config.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ip6-config.h" @@ -18,7 +18,7 @@ #include "nm-utils.h" #include "platform/nmp-object.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" #include "nm-ip4-config.h" @@ -158,7 +158,8 @@ nm_ip6_config_lookup_addresses(const NMIP6Config *self) void nm_ip_config_iter_ip6_address_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self) { - g_return_if_fail(NM_IS_IP6_CONFIG(self)); + nm_assert(NM_IS_IP6_CONFIG(self)); + nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_addresses(self)); } @@ -175,7 +176,8 @@ nm_ip6_config_lookup_routes(const NMIP6Config *self) void nm_ip_config_iter_ip6_route_init(NMDedupMultiIter *ipconf_iter, const NMIP6Config *self) { - g_return_if_fail(NM_IS_IP6_CONFIG(self)); + nm_assert(NM_IS_IP6_CONFIG(self)); + nm_dedup_multi_iter_init(ipconf_iter, nm_ip6_config_lookup_routes(self)); } @@ -1495,6 +1497,7 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self, NMIP6ConfigPrivate *priv; guint i; gboolean changed = FALSE; + gint32 base_time_sec; g_return_if_fail(NM_IS_IP6_CONFIG(self)); @@ -1502,6 +1505,16 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * 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++) { @@ -1514,9 +1527,13 @@ nm_ip6_config_reset_addresses_ndisc(NMIP6Config * self, a->ifindex = priv->ifindex; a->address = ndisc_addr->address; a->plen = plen; - a->timestamp = ndisc_addr->timestamp; - a->lifetime = ndisc_addr->lifetime; - a->preferred = MIN(ndisc_addr->lifetime, ndisc_addr->preferred); + 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; @@ -2554,12 +2571,12 @@ NMIP6Config * nm_ip6_config_new(NMDedupMultiIndex *multi_idx, int ifindex) { g_return_val_if_fail(ifindex >= -1, NULL); - return (NMIP6Config *) g_object_new(NM_TYPE_IP6_CONFIG, - NM_IP6_CONFIG_MULTI_IDX, - multi_idx, - NM_IP6_CONFIG_IFINDEX, - ifindex, - NULL); + return g_object_new(NM_TYPE_IP6_CONFIG, + NM_IP6_CONFIG_MULTI_IDX, + multi_idx, + NM_IP6_CONFIG_IFINDEX, + ifindex, + NULL); } NMIP6Config * diff --git a/src/nm-ip6-config.h b/src/core/nm-ip6-config.h index a5a28a1a..398186da 100644 --- a/src/nm-ip6-config.h +++ b/src/core/nm-ip6-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2013 Red Hat, Inc. */ diff --git a/src/nm-keep-alive.c b/src/core/nm-keep-alive.c index 2b6e19e8..197e30ea 100644 --- a/src/nm-keep-alive.c +++ b/src/core/nm-keep-alive.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-keep-alive.h" diff --git a/src/nm-keep-alive.h b/src/core/nm-keep-alive.h index 98c13273..2c2b4faa 100644 --- a/src/nm-keep-alive.h +++ b/src/core/nm-keep-alive.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/nm-l3-config-data.c b/src/core/nm-l3-config-data.c index 3cc5d670..5f9af7ac 100644 --- a/src/nm-l3-config-data.c +++ b/src/core/nm-l3-config-data.c @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-l3-config-data.h" @@ -11,7 +11,7 @@ #include "nm-glib-aux/nm-enum-utils.h" #include "nm-core-internal.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "platform/nmp-object.h" #include "NetworkManagerUtils.h" @@ -385,8 +385,10 @@ nm_l3_config_data_log(const NML3ConfigData *self, const NMPObject *obj; i = 0; - nm_l3_config_data_iter_obj_for_each(&iter, self, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + self, + &obj, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { _L("address%c[%u]: %s", nm_utils_addr_family_to_char(addr_family), i, @@ -407,8 +409,7 @@ nm_l3_config_data_log(const NML3ConfigData *self, } i = 0; - nm_l3_config_data_iter_obj_for_each(&iter, self, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, self, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { _L("route%c[%u]: %s%s", nm_utils_addr_family_to_char(addr_family), i, @@ -586,9 +587,7 @@ _route_valid_6(const NMPlatformIP6Route *r) static gboolean _route_valid(int addr_family, gconstpointer r) { - nm_assert_addr_family(addr_family); - - return addr_family == AF_INET ? _route_valid_4(r) : _route_valid_6(r); + return NM_IS_IPv4(addr_family) ? _route_valid_4(r) : _route_valid_6(r); } static gboolean @@ -914,8 +913,7 @@ nm_l3_config_data_has_routes_with_type_local(const NML3ConfigData *self, int add } val = FALSE; - nm_l3_config_data_iter_obj_for_each(&iter, self, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, self, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { if (NMP_OBJECT_CAST_IP_ROUTE(obj)->type_coerced == nm_platform_route_type_coerce(RTN_LOCAL)) { val = TRUE; @@ -989,8 +987,7 @@ nm_l3_config_data_get_first_obj(const NML3ConfigData *self, nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE)); - nm_l3_config_data_iter_obj_for_each(&iter, self, &obj, obj_type) - { + nm_l3_config_data_iter_obj_for_each (&iter, self, &obj, obj_type) { if (!predicate || predicate(obj)) return obj; } @@ -1205,8 +1202,7 @@ nm_l3_config_data_add_address_full(NML3ConfigData * self, nm_assert(!obj_new || NMP_OBJECT_GET_ADDR_FAMILY(obj_new) == addr_family); changed = _l3_config_data_add_obj(self->multi_idx, - addr_family == AF_INET ? &self->idx_addresses_4 - : &self->idx_addresses_6, + &self->idx_addresses_x[NM_IS_IPv4(addr_family)], self->ifindex, obj_new, (const NMPlatformObject *) pl_new, @@ -1253,7 +1249,7 @@ nm_l3_config_data_add_route_full(NML3ConfigData * self, else self->has_routes_with_type_local_6_set = FALSE; if (_l3_config_data_add_obj(self->multi_idx, - addr_family == AF_INET ? &self->idx_routes_4 : &self->idx_routes_6, + &self->idx_routes_x[NM_IS_IPv4(addr_family)], self->ifindex, obj_new, (const NMPlatformObject *) pl_new, @@ -1880,11 +1876,10 @@ _data_get_direct_route_for_host(const NML3ConfigData *self, if (nm_ip_addr_is_null(addr_family, host)) return NULL; - nm_l3_config_data_iter_obj_for_each(&ipconf_iter, - self, - &item_obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&ipconf_iter, + self, + &item_obj, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { const NMPlatformIPXRoute *item = NMP_OBJECT_CAST_IPX_ROUTE(item_obj); if (nm_ip_addr_is_null(addr_family, @@ -1941,8 +1936,7 @@ nm_l3_config_data_get_blacklisted_ip4_routes(const NML3ConfigData *self, gboolea * As we don't do that for IPv4 and manual IPv6 addresses. Add them here * as dependent routes. */ - nm_l3_config_data_iter_obj_for_each(&iter, self, &my_addr_obj, NMP_OBJECT_TYPE_IP4_ADDRESS) - { + nm_l3_config_data_iter_obj_for_each (&iter, self, &my_addr_obj, NMP_OBJECT_TYPE_IP4_ADDRESS) { const NMPlatformIP4Address *const my_addr = NMP_OBJECT_CAST_IP4_ADDRESS(my_addr_obj); in_addr_t network_4; NMPlatformIPXRoute rx; @@ -2033,11 +2027,10 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, nm_l3_config_data_add_route(self, addr_family, NULL, &rx.rx); } - nm_l3_config_data_iter_obj_for_each(&iter, - self, - &my_addr_obj, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + self, + &my_addr_obj, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { const NMPlatformIPXAddress *const my_addr = NMP_OBJECT_CAST_IPX_ADDRESS(my_addr_obj); if (my_addr->ax.external) @@ -2152,11 +2145,10 @@ nm_l3_config_data_add_dependent_routes(NML3ConfigData *self, } } - nm_l3_config_data_iter_obj_for_each(&iter, - self, - &my_route_obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + self, + &my_route_obj, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { const NMPlatformIPXRoute *my_route = NMP_OBJECT_CAST_IPX_ROUTE(my_route_obj); NMPObject * new_route; NMPlatformIPXRoute * new_r; @@ -2547,22 +2539,38 @@ nm_l3_config_data_merge(NML3ConfigData * self, const NML3ConfigDatFlags has_dns_priority_flag = NM_L3_CONFIG_DAT_FLAGS_HAS_DNS_PRIORITY(IS_IPv4); - nm_l3_config_data_iter_obj_for_each(&iter, src, &obj, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) - { - if (hook_add_addr && !hook_add_addr(src, obj, hook_user_data)) + nm_l3_config_data_iter_obj_for_each (&iter, + src, + &obj, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { + NMPlatformIPXAddress addr_stack; + const NMPlatformIPAddress *addr = NULL; + NMTernary ip4acd_not_ready = NM_TERNARY_DEFAULT; + + if (hook_add_addr && !hook_add_addr(src, obj, &ip4acd_not_ready, hook_user_data)) continue; + if (IS_IPv4 && ip4acd_not_ready != NM_TERNARY_DEFAULT + && (!!ip4acd_not_ready) != NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) { + addr_stack.a4 = *NMP_OBJECT_CAST_IP4_ADDRESS(obj); + addr_stack.a4.ip4acd_not_ready = (!!ip4acd_not_ready); + addr = &addr_stack.ax; + } else + nm_assert(IS_IPv4 || ip4acd_not_ready == NM_TERNARY_DEFAULT); + nm_l3_config_data_add_address_full(self, addr_family, - obj, - NULL, + addr ? NULL : obj, + addr, NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE, NULL); } if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_ROUTES)) { - nm_l3_config_data_iter_obj_for_each(&iter, src, &obj, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + src, + &obj, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj); NMPlatformIPXRoute r; @@ -2589,7 +2597,7 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (r_src->metric_any) { _ensure_r(); r.rx.metric_any = FALSE; - r.rx.metric_any = default_route_metric_x[IS_IPv4]; + r.rx.metric = nm_add_clamped_u32(r.rx.metric, default_route_metric_x[IS_IPv4]); } if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r_src)) { @@ -2655,8 +2663,7 @@ nm_l3_config_data_merge(NML3ConfigData * self, if (self->llmnr == NM_SETTING_CONNECTION_LLMNR_DEFAULT) self->llmnr = src->llmnr; - if (self->metered == NM_TERNARY_DEFAULT) - self->metered = src->metered; + self->metered = NM_MAX((NMTernary) self->metered, (NMTernary) src->metered); if (self->ip6_privacy == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) self->ip6_privacy = src->ip6_privacy; diff --git a/src/nm-l3-config-data.h b/src/core/nm-l3-config-data.h index 81dae7de..b3d9cd32 100644 --- a/src/nm-l3-config-data.h +++ b/src/core/nm-l3-config-data.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef __NM_L3_CONFIG_DATA_H__ #define __NM_L3_CONFIG_DATA_H__ @@ -141,6 +141,7 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex * mu typedef gboolean (*NML3ConfigMergeHookAddObj)(const NML3ConfigData *l3cd, const NMPObject * obj, + NMTernary * out_ip4acd_not_ready, gpointer user_data); void nm_l3_config_data_merge(NML3ConfigData * self, @@ -222,21 +223,13 @@ const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_objs(const NML3ConfigData static inline const NMDedupMultiHeadEntry * nm_l3_config_data_lookup_addresses(const NML3ConfigData *self, int addr_family) { - nm_assert_addr_family(addr_family); - - return nm_l3_config_data_lookup_objs(self, - addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ADDRESS - : NMP_OBJECT_TYPE_IP6_ADDRESS); + return nm_l3_config_data_lookup_objs(self, NMP_OBJECT_TYPE_IP_ADDRESS(NM_IS_IPv4(addr_family))); } static inline const NMDedupMultiHeadEntry * nm_l3_config_data_lookup_routes(const NML3ConfigData *self, int addr_family) { - nm_assert_addr_family(addr_family); - - return nm_l3_config_data_lookup_objs(self, - addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE); + return nm_l3_config_data_lookup_objs(self, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family))); } #define nm_l3_config_data_iter_obj_for_each(iter, self, obj, type) \ diff --git a/src/core/nm-l3-ipv4ll.c b/src/core/nm-l3-ipv4ll.c new file mode 100644 index 00000000..28ceb39e --- /dev/null +++ b/src/core/nm-l3-ipv4ll.c @@ -0,0 +1,1059 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-l3-ipv4ll.h" + +#include <net/if.h> +#include <linux/if_ether.h> + +#include "n-acd/src/n-acd.h" +#include "nm-core-utils.h" + +#define ADDR_IPV4LL_PREFIX_LEN 16 + +#define TIMED_OUT_TIME_FACTOR 5u + +/*****************************************************************************/ + +typedef enum { + TIMED_OUT_STATE_IS_NOT_TIMED_OUT, + TIMED_OUT_STATE_IS_TIMED_OUT, + TIMED_OUT_STATE_HAVE_TIMER_RUNNING, +} TimedOutState; + +struct _NML3IPv4LLRegistration { + NML3IPv4LL *self; + CList reg_lst; + guint timeout_msec; +}; + +G_STATIC_ASSERT(G_STRUCT_OFFSET(NML3IPv4LLRegistration, self) == 0); + +struct _NML3IPv4LL { + NML3Cfg * l3cfg; + int ref_count; + in_addr_t addr; + guint reg_timeout_msec; + CList reg_lst_head; + NML3CfgCommitTypeHandle *l3cfg_commit_handle; + GSource * state_change_on_idle_source; + GSource * timed_out_source; + const NML3ConfigData * l3cd; + const NMPObject * plobj; + struct { + nm_le64_t value; + nm_le64_t generation; + } seed; + gint64 timed_out_expiry_msec; + gulong l3cfg_signal_notify_id; + NML3IPv4LLState state; + NMEtherAddr seed_mac; + NMEtherAddr mac; + bool seed_set : 1; + bool mac_set : 1; + bool notify_on_idle : 1; + bool reg_changed : 1; + bool l3cd_timeout_msec_changed : 1; + + /* not yet used. */ + bool seed_reset_generation : 1; +}; + +G_STATIC_ASSERT(G_STRUCT_OFFSET(NML3IPv4LL, ref_count) == sizeof(gpointer)); + +#define L3CD_TAG(self) (&(((const char *) self)[1])) + +/*****************************************************************************/ + +#define _NMLOG_DOMAIN LOGD_IP4 +#define _NMLOG_PREFIX_NAME "ipv4ll" +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + nm_log((level), \ + (_NMLOG_DOMAIN), \ + NULL, \ + NULL, \ + _NMLOG_PREFIX_NAME "[" NM_HASH_OBFUSCATE_PTR_FMT \ + ",ifindex=%d]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + NM_HASH_OBFUSCATE_PTR(self), \ + nm_l3cfg_get_ifindex((self)->l3cfg) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END + +/*****************************************************************************/ + +static void _ipv4ll_state_change_on_idle(NML3IPv4LL *self); + +static void _ipv4ll_state_change(NML3IPv4LL *self, gboolean is_on_idle_handler); + +static void _ipv4ll_set_timed_out_update(NML3IPv4LL *self, TimedOutState new_state); + +/*****************************************************************************/ + +NM_UTILS_ENUM2STR_DEFINE(nm_l3_ipv4ll_state_to_string, + NML3IPv4LLState, + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_UNKNOWN, "unknown"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_DISABLED, "disabled"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_WAIT_FOR_LINK, "wait-for-link"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_EXTERNAL, "external"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_PROBING, "probing"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_DEFENDING, "defending"), + NM_UTILS_ENUM2STR(NM_L3_IPV4LL_STATE_READY, "ready"), ); + +/*****************************************************************************/ + +#define _ASSERT(self) \ + G_STMT_START \ + { \ + NML3IPv4LL *const _self = (self); \ + \ + nm_assert(NM_IS_L3_IPV4LL(_self)); \ + if (NM_MORE_ASSERTS > 5) { \ + nm_assert(_self->addr == 0u || nm_utils_ip4_address_is_link_local(_self->addr)); \ + nm_assert(!_self->l3cd || NM_IS_L3_CONFIG_DATA(_self->l3cd)); \ + } \ + } \ + G_STMT_END + +/*****************************************************************************/ + +NML3Cfg * +nm_l3_ipv4ll_get_l3cfg(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return self->l3cfg; +} + +int +nm_l3_ipv4ll_get_ifindex(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return nm_l3cfg_get_ifindex(self->l3cfg); +} + +NMPlatform * +nm_l3_ipv4ll_get_platform(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return nm_l3cfg_get_platform(self->l3cfg); +} + +/*****************************************************************************/ + +NML3IPv4LLState +nm_l3_ipv4ll_get_state(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return self->state; +} + +static gboolean +_ipv4ll_is_timed_out(NML3IPv4LL *self) +{ + _ASSERT(self); + + return self->timed_out_expiry_msec != 0 && !self->timed_out_source; +} + +gboolean +nm_l3_ipv4ll_is_timed_out(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return _ipv4ll_is_timed_out(self); +} + +in_addr_t +nm_l3_ipv4ll_get_addr(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return self->addr; +} + +const NML3ConfigData * +nm_l3_ipv4ll_get_l3cd(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + return self->l3cd; +} + +static void +_ipv4ll_emit_signal_notify(NML3IPv4LL *self) +{ + NML3ConfigNotifyData notify_data; + + self->notify_on_idle = FALSE; + + notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT; + notify_data.ipv4ll_event = (typeof(notify_data.ipv4ll_event)){ + .ipv4ll = self, + }; + _nm_l3cfg_emit_signal_notify(self->l3cfg, ¬ify_data); +} + +/*****************************************************************************/ + +static NML3IPv4LLRegistration * +_registration_update(NML3IPv4LL * self, + NML3IPv4LLRegistration *reg, + gboolean add, + guint timeout_msec) +{ + nm_auto_unref_l3ipv4ll NML3IPv4LL *self_unref_on_exit = NULL; + gboolean changed = FALSE; + + if (reg) { + nm_assert(!self); + _ASSERT(reg->self); + self = reg->self; + nm_assert(c_list_contains(&self->reg_lst_head, ®->reg_lst)); + nm_assert(self == nm_l3_ipv4ll_register_get_instance(reg)); + } else { + nm_assert(add); + _ASSERT(self); + } + + if (!add) { + _LOGT("registration[" NM_HASH_OBFUSCATE_PTR_FMT "]: remove", NM_HASH_OBFUSCATE_PTR(reg)); + c_list_unlink_stale(®->reg_lst); + if (c_list_is_empty(&self->reg_lst_head)) + self_unref_on_exit = self; + nm_g_slice_free(reg); + reg = NULL; + goto out; + } + + if (!reg) { + reg = g_slice_new(NML3IPv4LLRegistration); + *reg = (NML3IPv4LLRegistration){ + .self = self, + .timeout_msec = timeout_msec, + }; + + if (c_list_is_empty(&self->reg_lst_head)) + nm_l3_ipv4ll_ref(self); + c_list_link_tail(&self->reg_lst_head, ®->reg_lst); + changed = TRUE; + _LOGT("registration[" NM_HASH_OBFUSCATE_PTR_FMT "]: add (timeout_msec=%u)", + NM_HASH_OBFUSCATE_PTR(reg), + timeout_msec); + } else { + if (reg->timeout_msec != timeout_msec) { + reg->timeout_msec = timeout_msec; + changed = TRUE; + } + if (changed) { + _LOGT("registration[" NM_HASH_OBFUSCATE_PTR_FMT "]: update (timeout_msec=%u)", + NM_HASH_OBFUSCATE_PTR(reg), + timeout_msec); + } + } + +out: + if (changed) { + self->reg_changed = TRUE; + _ipv4ll_state_change(self, FALSE); + } + return reg; +} + +NML3IPv4LLRegistration * +nm_l3_ipv4ll_register_new(NML3IPv4LL *self, guint timeout_msec) +{ + return _registration_update(self, NULL, TRUE, timeout_msec); +} + +NML3IPv4LLRegistration * +nm_l3_ipv4ll_register_update(NML3IPv4LLRegistration *reg, guint timeout_msec) +{ + return _registration_update(NULL, reg, TRUE, timeout_msec); +} + +NML3IPv4LLRegistration * +nm_l3_ipv4ll_register_remove(NML3IPv4LLRegistration *reg) +{ + return _registration_update(NULL, reg, FALSE, 0); +} + +/*****************************************************************************/ + +static gboolean +_ip4_address_is_link_local(const NMPlatformIP4Address *a) +{ + nm_assert(a); + + return nm_utils_ip4_address_is_link_local(a->address) && a->plen == ADDR_IPV4LL_PREFIX_LEN + && a->address == a->peer_address; +} + +static gboolean +_acd_info_is_good(const NML3AcdAddrInfo *acd_info) +{ + if (!acd_info) + return TRUE; + + switch (acd_info->state) { + case NM_L3_ACD_ADDR_STATE_INIT: + case NM_L3_ACD_ADDR_STATE_PROBING: + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + return TRUE; + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + return FALSE; + } + nm_assert_not_reached(); + return FALSE; +} + +/*****************************************************************************/ + +static NMPlatformIP4Address * +_l3cd_config_plat_init_addr(NMPlatformIP4Address *a, int ifindex, in_addr_t addr) +{ + nm_assert(nm_utils_ip4_address_is_link_local(addr)); + + *a = (NMPlatformIP4Address){ + .ifindex = ifindex, + .address = addr, + .peer_address = addr, + .plen = ADDR_IPV4LL_PREFIX_LEN, + .addr_source = NM_IP_CONFIG_SOURCE_IP4LL, + }; + return a; +} + +static NMPlatformIP4Route * +_l3cd_config_plat_init_route(NMPlatformIP4Route *r, int ifindex) +{ + *r = (NMPlatformIP4Route){ + .ifindex = ifindex, + .network = htonl(0xE0000000u), + .plen = 4, + .rt_source = NM_IP_CONFIG_SOURCE_IP4LL, + .table_any = TRUE, + .metric_any = TRUE, + }; + return r; +} + +static const NML3ConfigData * +_l3cd_config_create(int ifindex, in_addr_t addr, NMDedupMultiIndex *multi_idx) +{ + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + NMPlatformIP4Address a; + NMPlatformIP4Route r; + + nm_assert(nm_utils_ip4_address_is_link_local(addr)); + nm_assert(ifindex > 0); + nm_assert(multi_idx); + + l3cd = nm_l3_config_data_new(multi_idx, ifindex); + nm_l3_config_data_set_source(l3cd, NM_IP_CONFIG_SOURCE_IP4LL); + + nm_l3_config_data_add_address_4(l3cd, _l3cd_config_plat_init_addr(&a, ifindex, addr)); + nm_l3_config_data_add_route_4(l3cd, _l3cd_config_plat_init_route(&r, ifindex)); + + return nm_l3_config_data_seal(g_steal_pointer(&l3cd)); +} + +static in_addr_t +_l3cd_config_get_addr(const NML3ConfigData *l3cd) +{ + NMDedupMultiIter iter; + const NMPlatformIP4Address *pladdr; + + if (!l3cd) + return 0u; + + nm_l3_config_data_iter_ip4_address_for_each (&iter, l3cd, &pladdr) { + const in_addr_t addr = pladdr->address; + + nm_assert(_ip4_address_is_link_local(pladdr)); +#if NM_MORE_ASSERTS > 10 + { + nm_auto_unref_l3cd const NML3ConfigData *l3cd2 = NULL; + + l3cd2 = _l3cd_config_create(nm_l3_config_data_get_ifindex(l3cd), + addr, + nm_l3_config_data_get_multi_idx(l3cd)); + nm_assert(nm_l3_config_data_equal(l3cd2, l3cd)); + } +#endif + return addr; + } + + return nm_assert_unreachable_val(0u); +} + +/*****************************************************************************/ + +static void +_ipv4ll_addrgen(NML3IPv4LL *self, gboolean generate_new_addr) +{ + CSipHash state; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + gboolean seed_changed = FALSE; + in_addr_t addr_new; + guint64 h; + + _ASSERT(self); + + /* MAC_HASH_KEY is the same as used by systemd. */ +#define MAC_HASH_KEY \ + ((const guint8[16]){0xdf, \ + 0x04, \ + 0x22, \ + 0x98, \ + 0x3f, \ + 0xad, \ + 0x14, \ + 0x52, \ + 0xf9, \ + 0x87, \ + 0x2e, \ + 0xd1, \ + 0x9c, \ + 0x70, \ + 0xe2, \ + 0xf2}) + + if (self->mac_set && (!self->seed_set || !nm_ether_addr_equal(&self->mac, &self->seed_mac))) { + /* systemd's ipv4ll library by default only hashes the MAC address (as we do here). + * This is also what previous versions of NetworkManager did (whenn using sd_ipv4ll). + * + * On the other hand, systemd-networkd uses net_get_name_persistent() of the device + * mixed with /etc/machine-id. + * + * See also: https://tools.ietf.org/html/rfc3927#section-2.1 + * + * FIXME(l3cfg): At this point, maybe we should also mix it with nm_utils_host_id_get(). + * This would get the behavior closer to what systemd-networkd does. + * Don't do that for now, because it would be a change in behavior compared + * to earlier versions of NetworkManager. */ + + c_siphash_init(&state, MAC_HASH_KEY); + c_siphash_append(&state, self->mac.ether_addr_octet, ETH_ALEN); + h = c_siphash_finalize(&state); + + _LOGT("addr-gen: %sset seed (for " NM_ETHER_ADDR_FORMAT_STR ")", + self->seed_set ? "re" : "", + NM_ETHER_ADDR_FORMAT_VAL(&self->mac)); + + self->seed_set = TRUE; + self->seed_mac = self->mac; + self->seed.generation = htole64(0); + self->seed.value = htole64(h); + self->seed_reset_generation = FALSE; + self->addr = 0u; + + seed_changed = TRUE; + } + + if (!self->seed_set) { + /* we have no seed set (and consequently no MAC address set either). + * We cannot generate an address. */ + nm_assert(self->addr == 0u); + return; + } + + nm_assert(seed_changed || self->seed.generation != htole64(0u)); + + if (self->seed_reset_generation) { + _LOGT("addr-gen: reset seed (generation only)"); + self->seed.generation = htole64(0); + self->addr = 0u; + seed_changed = TRUE; + } + + if (!seed_changed && !generate_new_addr) { + /* neither did the caller request a new address, nor was the seed changed. The current + * address is still to be used. */ + nm_assert(nm_utils_ip4_address_is_link_local(self->addr)); + return; + } + +gen_addr: + +#define PICK_HASH_KEY \ + ((const guint8[16]){0x15, \ + 0xac, \ + 0x82, \ + 0xa6, \ + 0xd6, \ + 0x3f, \ + 0x49, \ + 0x78, \ + 0x98, \ + 0x77, \ + 0x5d, \ + 0x0c, \ + 0x69, \ + 0x02, \ + 0x94, \ + 0x0b}) + + h = c_siphash_hash(PICK_HASH_KEY, (const guint8 *) &self->seed, sizeof(self->seed)); + + self->seed.generation = htole64(le64toh(self->seed.generation) + 1u); + + addr_new = htonl(h & UINT32_C(0x0000FFFF)) | NM_IPV4LL_NETWORK; + + if (self->addr == addr_new || NM_IN_SET(ntohl(addr_new) & 0x0000FF00u, 0x0000u, 0xFF00u)) + goto gen_addr; + + nm_assert(nm_utils_ip4_address_is_link_local(addr_new)); + + _LOGT("addr-gen: set address %s", _nm_utils_inet4_ntop(addr_new, sbuf_addr)); + self->addr = addr_new; +} + +/*****************************************************************************/ + +static void +_ipv4ll_update_link(NML3IPv4LL *self, const NMPObject *plobj) +{ + char sbuf[ETH_ALEN * 3]; + nm_auto_nmpobj const NMPObject *pllink_old = NULL; + const NMEtherAddr * mac_new; + gboolean changed; + + if (self->plobj == plobj) + return; + + pllink_old = g_steal_pointer(&self->plobj); + self->plobj = nmp_object_ref(plobj); + + mac_new = NULL; + if (plobj) { + const NMPlatformLink *pllink = NMP_OBJECT_CAST_LINK(plobj); + + if (pllink->l_address.len == ETH_ALEN) + mac_new = &pllink->l_address.ether_addr; + } + + changed = FALSE; + if (!mac_new) { + if (self->mac_set) { + changed = TRUE; + self->mac_set = FALSE; + } + } else { + if (!self->mac_set || !nm_ether_addr_equal(mac_new, &self->mac)) { + changed = TRUE; + self->mac_set = TRUE; + self->mac = *mac_new; + } + } + + if (changed) { + _LOGT("mac changed: %s", + self->mac_set ? _nm_utils_hwaddr_ntoa(&self->mac, ETH_ALEN, TRUE, sbuf, sizeof(sbuf)) + : "unset"); + } +} + +/*****************************************************************************/ + +static void +_l3cd_config_add(NML3IPv4LL *self) +{ + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + gboolean changed; + + _ASSERT(self); + nm_assert(self->addr != 0u); + nm_assert(self->reg_timeout_msec > 0u); + + if (_l3cd_config_get_addr(self->l3cd) != self->addr) { + l3cd = _l3cd_config_create(nm_l3_ipv4ll_get_ifindex(self), + self->addr, + nm_l3cfg_get_multi_idx(self->l3cfg)); + nm_assert(!nm_l3_config_data_equal(l3cd, self->l3cd)); + changed = TRUE; + } else + changed = FALSE; + + if (!changed && !self->l3cd_timeout_msec_changed) + return; + + self->l3cd_timeout_msec_changed = FALSE; + + _LOGT("add l3cd config with %s (acd-timeout %u msec%s)", + _nm_utils_inet4_ntop(self->addr, sbuf_addr), + self->reg_timeout_msec, + changed ? "" : " changed"); + + if (changed) { + NM_SWAP(&l3cd, &self->l3cd); + self->notify_on_idle = TRUE; + } + + if (!nm_l3cfg_add_config(self->l3cfg, + L3CD_TAG(self), + TRUE, + self->l3cd, + NM_L3CFG_CONFIG_PRIORITY_IPV4LL, + 0, + 0, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, + 0, + 0, + NM_L3_ACD_DEFEND_TYPE_ONCE, + self->reg_timeout_msec, + NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD)) + nm_assert_not_reached(); + + self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg, + NM_L3_CFG_COMMIT_TYPE_ASSUME, + self->l3cfg_commit_handle); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg); +} + +static gboolean +_l3cd_config_remove(NML3IPv4LL *self) +{ + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + + nm_assert(NM_IS_L3_IPV4LL(self)); + + if (!self->l3cd) + return FALSE; + + _LOGT("remove l3cd config"); + + self->notify_on_idle = TRUE; + + l3cd = g_steal_pointer(&self->l3cd); + if (!nm_l3cfg_remove_config(self->l3cfg, L3CD_TAG(self), l3cd)) + nm_assert_not_reached(); + + nm_l3cfg_commit_type_unregister(self->l3cfg, g_steal_pointer(&self->l3cfg_commit_handle)); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg); + return TRUE; +} + +/*****************************************************************************/ + +static const NMPlatformIP4Address * +_ipv4ll_platform_ip4_address_lookup(NML3IPv4LL *self, in_addr_t addr) +{ + const NMPlatformIP4Address *pladdr; + + if (addr == 0u) + return NULL; + + nm_assert(nm_utils_ip4_address_is_link_local(addr)); + + pladdr = nm_platform_ip4_address_get(nm_l3_ipv4ll_get_platform(self), + nm_l3_ipv4ll_get_ifindex(self), + addr, + ADDR_IPV4LL_PREFIX_LEN, + addr); + + nm_assert(!pladdr || pladdr->address == addr); + nm_assert(!pladdr || _ip4_address_is_link_local(pladdr)); + return pladdr; +} + +static const NML3AcdAddrInfo * +_ipv4ll_l3cfg_get_acd_addr_info(NML3IPv4LL *self, in_addr_t addr) +{ + if (addr == 0u) + return NULL; + + nm_assert(nm_utils_ip4_address_is_link_local(addr)); + return nm_l3cfg_get_acd_addr_info(self->l3cfg, addr); +} + +static const NMPlatformIP4Address * +_ipv4ll_platform_find_addr(NML3IPv4LL *self, const NML3AcdAddrInfo **out_acd_info) +{ + const NMPlatformIP4Address *addr_without_acd_info = NULL; + NMDedupMultiIter iter; + NMPLookup lookup; + const NMPObject * obj; + const NML3AcdAddrInfo * acd_info; + const NMPlatformIP4Address *addr; + + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP4_ADDRESS, nm_l3_ipv4ll_get_ifindex(self)); + nm_platform_iter_obj_for_each (&iter, nm_l3_ipv4ll_get_platform(self), &lookup, &obj) { + addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj); + if (!_ip4_address_is_link_local(addr)) + continue; + + acd_info = _ipv4ll_l3cfg_get_acd_addr_info(self, addr->address); + if (!_acd_info_is_good(acd_info)) + continue; + + if (acd_info) { + /* We have a good acd_info. We won't find a better one. Return it. */ + NM_SET_OUT(out_acd_info, acd_info); + return addr; + } + + if (!addr_without_acd_info) { + /* remember a potential candidate address that has no acd_info. */ + addr_without_acd_info = addr; + } + } + + if (addr_without_acd_info) { + NM_SET_OUT(out_acd_info, NULL); + return addr_without_acd_info; + } + + return NULL; +} + +/*****************************************************************************/ + +static gboolean +_ipv4ll_set_timed_out_timeout_cb(gpointer user_data) +{ + NML3IPv4LL *self = user_data; + + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_IS_TIMED_OUT); + if (self->notify_on_idle) + _ipv4ll_emit_signal_notify(self); + return G_SOURCE_REMOVE; +} + +static void +_ipv4ll_set_timed_out_update(NML3IPv4LL *self, TimedOutState new_state) +{ + gboolean before; + + before = _ipv4ll_is_timed_out(self); + + switch (new_state) { + case TIMED_OUT_STATE_IS_TIMED_OUT: + if (self->timed_out_expiry_msec == 0) { + nm_assert(!self->timed_out_source); + self->timed_out_expiry_msec = 1; + } + nm_clear_g_source_inst(&self->timed_out_source); + break; + case TIMED_OUT_STATE_IS_NOT_TIMED_OUT: + self->timed_out_expiry_msec = 0; + nm_clear_g_source_inst(&self->timed_out_source); + break; + case TIMED_OUT_STATE_HAVE_TIMER_RUNNING: + { + gint64 now_msec = nm_utils_get_monotonic_timestamp_msec(); + guint timeout_msec; + gint64 expiry_msec; + + nm_assert(self->reg_timeout_msec > 0u); + + timeout_msec = nm_mult_clamped_u(TIMED_OUT_TIME_FACTOR, self->reg_timeout_msec); + expiry_msec = now_msec + timeout_msec; + + if (self->timed_out_expiry_msec == 0 || self->timed_out_expiry_msec < expiry_msec) { + self->timed_out_expiry_msec = expiry_msec; + nm_clear_g_source_inst(&self->timed_out_source); + self->timed_out_source = nm_g_timeout_source_new(timeout_msec, + G_PRIORITY_DEFAULT, + _ipv4ll_set_timed_out_timeout_cb, + self, + NULL); + g_source_attach(self->timed_out_source, NULL); + } + break; + } + } + + if (before != _ipv4ll_is_timed_out(self)) { + self->notify_on_idle = TRUE; + _LOGT("state: set timed-out-is-bad=%d", (!before)); + } +} + +static gboolean +_ipv4ll_set_state(NML3IPv4LL *self, NML3IPv4LLState state) +{ + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + char sbuf100[100]; + + if (self->state == state) + return FALSE; + self->state = state; + self->notify_on_idle = TRUE; + _LOGT("state: set state %s (addr=%s)", + nm_l3_ipv4ll_state_to_string(state, sbuf100, sizeof(sbuf100)), + _nm_utils_inet4_ntop(self->addr, sbuf_addr)); + return TRUE; +} + +static void +_ipv4ll_state_change(NML3IPv4LL *self, gboolean is_on_idle_handler) +{ + nm_auto_unref_l3ipv4ll NML3IPv4LL *self_keep_alive = NULL; + const NMPlatformIP4Address * pladdr; + const NML3AcdAddrInfo * acd_info; + gboolean generate_new_addr; + NML3IPv4LLState new_state; + in_addr_t addr0; + NML3IPv4LLRegistration * reg; + + _ASSERT(self); + + self_keep_alive = nm_l3_ipv4ll_ref(self); + + nm_clear_g_source_inst(&self->state_change_on_idle_source); + + addr0 = self->addr; + + if (self->reg_changed) { + guint timeout_msec = self->reg_timeout_msec; + + self->reg_changed = FALSE; + + if (c_list_is_empty(&self->reg_lst_head)) + timeout_msec = 0; + else { + timeout_msec = G_MAXUINT; + c_list_for_each_entry (reg, &self->reg_lst_head, reg_lst) { + if (reg->timeout_msec < timeout_msec) + timeout_msec = reg->timeout_msec; + if (reg->timeout_msec == 0) + break; + } + } + if (self->reg_timeout_msec != timeout_msec) { + self->reg_timeout_msec = timeout_msec; + self->l3cd_timeout_msec_changed = TRUE; + } + } + + if (self->reg_timeout_msec == 0) { + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_IS_NOT_TIMED_OUT); + if (_ipv4ll_set_state(self, NM_L3_IPV4LL_STATE_DISABLED)) + _l3cd_config_remove(self); + goto out_notify; + } + + if (!self->mac_set) { + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_HAVE_TIMER_RUNNING); + if (_ipv4ll_set_state(self, NM_L3_IPV4LL_STATE_WAIT_FOR_LINK)) + _l3cd_config_remove(self); + else + nm_assert(!self->l3cd); + goto out_notify; + } + + if (self->state <= NM_L3_IPV4LL_STATE_EXTERNAL) { + pladdr = _ipv4ll_platform_ip4_address_lookup(self, self->addr); + if (pladdr) { + if (!_acd_info_is_good(_ipv4ll_l3cfg_get_acd_addr_info(self, self->addr))) + pladdr = NULL; + } + if (!pladdr) + pladdr = _ipv4ll_platform_find_addr(self, NULL); + + if (pladdr) { + /* we have an externally configured address. Check whether we can use it. */ + self->addr = pladdr->address; + self->notify_on_idle = TRUE; + _ipv4ll_set_state(self, NM_L3_IPV4LL_STATE_EXTERNAL); + _l3cd_config_add(self); + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_IS_NOT_TIMED_OUT); + goto out_notify; + } + } + + generate_new_addr = FALSE; + while (TRUE) { + _ipv4ll_addrgen(self, generate_new_addr); + acd_info = _ipv4ll_l3cfg_get_acd_addr_info(self, self->addr); + if (_acd_info_is_good(acd_info)) + break; + generate_new_addr = TRUE; + } + + nm_assert(_acd_info_is_good(acd_info)); + switch (acd_info ? acd_info->state : NM_L3_ACD_ADDR_STATE_INIT) { + case NM_L3_ACD_ADDR_STATE_INIT: + case NM_L3_ACD_ADDR_STATE_PROBING: + new_state = NM_L3_IPV4LL_STATE_PROBING; + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_HAVE_TIMER_RUNNING); + goto out_is_good_1; + case NM_L3_ACD_ADDR_STATE_READY: + new_state = NM_L3_IPV4LL_STATE_READY; + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_HAVE_TIMER_RUNNING); + goto out_is_good_1; + case NM_L3_ACD_ADDR_STATE_DEFENDING: + new_state = NM_L3_IPV4LL_STATE_DEFENDING; + _ipv4ll_set_timed_out_update(self, TIMED_OUT_STATE_IS_NOT_TIMED_OUT); + goto out_is_good_1; + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + nm_assert_not_reached(); + goto out_notify; + } + nm_assert_not_reached(); + goto out_notify; +out_is_good_1: + _ipv4ll_set_state(self, new_state); + _l3cd_config_add(self); + if (self->addr != addr0) + self->notify_on_idle = TRUE; + goto out_notify; + +out_notify: + if (self->notify_on_idle) { + if (is_on_idle_handler) + _ipv4ll_emit_signal_notify(self); + else + _ipv4ll_state_change_on_idle(self); + } +} + +static gboolean +_ipv4ll_state_change_on_idle_cb(gpointer user_data) +{ + NML3IPv4LL *self = user_data; + + _ipv4ll_state_change(self, TRUE); + return G_SOURCE_REMOVE; +} + +static void +_ipv4ll_state_change_on_idle(NML3IPv4LL *self) +{ + nm_assert(NM_IS_L3_IPV4LL(self)); + + if (!self->state_change_on_idle_source) { + self->state_change_on_idle_source = + nm_g_idle_source_new(G_PRIORITY_DEFAULT, _ipv4ll_state_change_on_idle_cb, self, NULL); + g_source_attach(self->state_change_on_idle_source, NULL); + } +} + +/*****************************************************************************/ + +static void +_l3cfg_notify_cb(NML3Cfg *l3cfg, const NML3ConfigNotifyData *notify_data, NML3IPv4LL *self) +{ + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE) { + /* NMl3Cfg only reloads the platform link during the idle handler. Pick it up now. */ + _ipv4ll_update_link(self, nm_l3cfg_get_plobj(l3cfg, FALSE)); + + /* theoretically, this even is already on an idle handler. However, we share + * the call with other signal handlers, so at this point we don't want to + * emit additional signals. Thus pass %FALSE to _ipv4ll_state_change(). */ + _ipv4ll_state_change(self, FALSE); + return; + } + + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT) { + if (self->l3cd + && nm_l3_acd_addr_info_find_track_info(¬ify_data->acd_event.info, + L3CD_TAG(self), + self->l3cd, + NULL)) { + _ipv4ll_state_change(self, FALSE); + } + return; + } +} + +/*****************************************************************************/ + +NML3IPv4LL * +nm_l3_ipv4ll_new(NML3Cfg *l3cfg) +{ + NML3IPv4LL *self; + + g_return_val_if_fail(NM_IS_L3CFG(l3cfg), NULL); + + self = g_slice_new(NML3IPv4LL); + *self = (NML3IPv4LL){ + .l3cfg = g_object_ref(l3cfg), + .ref_count = 1, + .reg_lst_head = C_LIST_INIT(self->reg_lst_head), + .l3cfg_commit_handle = NULL, + .state_change_on_idle_source = NULL, + .l3cd = NULL, + .plobj = NULL, + .addr = 0u, + .state = NM_L3_IPV4LL_STATE_DISABLED, + .reg_timeout_msec = 0, + .notify_on_idle = TRUE, + .l3cfg_signal_notify_id = + g_signal_connect(l3cfg, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_l3cfg_notify_cb), self), + .seed_set = FALSE, + .seed_reset_generation = FALSE, + }; + + _LOGT("created: l3cfg=" NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(l3cfg)); + + _ipv4ll_update_link(self, nm_l3cfg_get_plobj(l3cfg, FALSE)); + _ipv4ll_state_change(self, FALSE); + return self; +} + +NML3IPv4LL * +nm_l3_ipv4ll_ref(NML3IPv4LL *self) +{ + if (!self) + return NULL; + + _ASSERT(self); + + nm_assert(self->ref_count < G_MAXINT); + self->ref_count++; + return self; +} + +void +nm_l3_ipv4ll_unref(NML3IPv4LL *self) +{ + if (!self) + return; + + _ASSERT(self); + + if (--self->ref_count > 0) + return; + + if (nm_l3cfg_get_ipv4ll(self->l3cfg) == self) + _nm_l3cfg_unregister_ipv4ll(self->l3cfg); + + _LOGT("finalize"); + + nm_assert(c_list_is_empty(&self->reg_lst_head)); + + if (self->l3cd) { + nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; + + l3cd = g_steal_pointer(&self->l3cd); + if (!nm_l3cfg_remove_config(self->l3cfg, L3CD_TAG(self), l3cd)) + nm_assert_not_reached(); + + nm_l3cfg_commit_type_unregister(self->l3cfg, g_steal_pointer(&self->l3cfg_commit_handle)); + nm_l3cfg_commit_on_idle_schedule(self->l3cfg); + } else + nm_assert(!self->l3cfg_commit_handle); + + nm_clear_g_source_inst(&self->state_change_on_idle_source); + nm_clear_g_source_inst(&self->timed_out_source); + + nm_clear_g_signal_handler(self->l3cfg, &self->l3cfg_signal_notify_id); + + g_clear_object(&self->l3cfg); + nmp_object_unref(self->plobj); + nm_g_slice_free(self); +} diff --git a/src/core/nm-l3-ipv4ll.h b/src/core/nm-l3-ipv4ll.h new file mode 100644 index 00000000..b39762a8 --- /dev/null +++ b/src/core/nm-l3-ipv4ll.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#ifndef __NM_L3_IPV4LL_H__ +#define __NM_L3_IPV4LL_H__ + +#include "nm-l3cfg.h" + +/*****************************************************************************/ + +typedef enum _nm_packed { + NM_L3_IPV4LL_STATE_UNKNOWN, + NM_L3_IPV4LL_STATE_DISABLED, + NM_L3_IPV4LL_STATE_WAIT_FOR_LINK, + NM_L3_IPV4LL_STATE_EXTERNAL, + NM_L3_IPV4LL_STATE_PROBING, + NM_L3_IPV4LL_STATE_READY, + NM_L3_IPV4LL_STATE_DEFENDING, +} NML3IPv4LLState; + +const char *nm_l3_ipv4ll_state_to_string(NML3IPv4LLState val, char *buf, gsize len); + +static inline gboolean +nm_l3_ipv4ll_state_is_good(NML3IPv4LLState state) +{ + switch (state) { + case NM_L3_IPV4LL_STATE_UNKNOWN: + case NM_L3_IPV4LL_STATE_DISABLED: + case NM_L3_IPV4LL_STATE_WAIT_FOR_LINK: + case NM_L3_IPV4LL_STATE_PROBING: + return FALSE; + case NM_L3_IPV4LL_STATE_EXTERNAL: + case NM_L3_IPV4LL_STATE_READY: + case NM_L3_IPV4LL_STATE_DEFENDING: + return TRUE; + } + return nm_assert_unreachable_val(FALSE); +} + +/*****************************************************************************/ + +typedef struct _NML3IPv4LL NML3IPv4LL; + +static inline gboolean +NM_IS_L3_IPV4LL(const NML3IPv4LL *self) +{ + nm_assert(!self + || (NM_IS_L3CFG(*((NML3Cfg **) self)) + && (*((int *) (((char *) self) + sizeof(gpointer)))) > 0)); + return !!self; +} + +NML3IPv4LL *nm_l3_ipv4ll_new(NML3Cfg *self); + +NML3IPv4LL *nm_l3_ipv4ll_ref(NML3IPv4LL *self); +void nm_l3_ipv4ll_unref(NML3IPv4LL *self); + +NM_AUTO_DEFINE_FCN0(NML3IPv4LL *, _nm_auto_unref_l3ipv4ll, nm_l3_ipv4ll_unref); +#define nm_auto_unref_l3ipv4ll nm_auto(_nm_auto_unref_l3ipv4ll) + +/*****************************************************************************/ + +NML3Cfg *nm_l3_ipv4ll_get_l3cfg(NML3IPv4LL *self); + +int nm_l3_ipv4ll_get_ifindex(NML3IPv4LL *self); + +NMPlatform *nm_l3_ipv4ll_get_platform(NML3IPv4LL *self); + +/*****************************************************************************/ + +/* By default, NML3IPv4LL is disabled. You also need to register (enable) it. + * The intent of this API is that multiple users can enable/register their own + * settings, and NML3IPv4LL will mediate the different requests. + * + * Also, by setting timeout_msec to zero, NML3IPv4LL is disabled again (zero + * wins over all timeouts). This is useful if you do DHCP and IPv4LL on the + * same interface. You possibly want to disable IPv4LL if you have a valid + * DHCP lease. By registering a timeout_msec to zero, you can disable IPv4LL. + * + * Also, a registration keeps the NML3IPv4LL instance alive (it also takes + * a reference). */ + +typedef struct _NML3IPv4LLRegistration NML3IPv4LLRegistration; + +NML3IPv4LLRegistration *nm_l3_ipv4ll_register_new(NML3IPv4LL *self, guint timeout_msec); + +NML3IPv4LLRegistration *nm_l3_ipv4ll_register_update(NML3IPv4LLRegistration *reg, + guint timeout_msec); + +NML3IPv4LLRegistration *nm_l3_ipv4ll_register_remove(NML3IPv4LLRegistration *reg); + +NM_AUTO_DEFINE_FCN0(NML3IPv4LLRegistration *, + _nm_auto_remove_l3ipv4ll_registration, + nm_l3_ipv4ll_register_remove); +#define nm_auto_remove_l3ipv4ll_registration nm_auto(_nm_auto_remove_l3ipv4ll_registration) + +static inline NML3IPv4LL * +nm_l3_ipv4ll_register_get_instance(NML3IPv4LLRegistration *reg) +{ + NML3IPv4LL *ipv4ll; + + if (!reg) + return NULL; + ipv4ll = *((NML3IPv4LL **) reg); + nm_assert(NM_IS_L3_IPV4LL(ipv4ll)); + return ipv4ll; +} + +/*****************************************************************************/ + +NML3IPv4LLState nm_l3_ipv4ll_get_state(NML3IPv4LL *self); + +gboolean nm_l3_ipv4ll_is_timed_out(NML3IPv4LL *self); + +in_addr_t nm_l3_ipv4ll_get_addr(NML3IPv4LL *self); + +const NML3ConfigData *nm_l3_ipv4ll_get_l3cd(NML3IPv4LL *self); + +#endif /* __NM_L3_IPV4LL_H__ */ diff --git a/src/nm-l3cfg.c b/src/core/nm-l3cfg.c index 7b1e6f22..839213ad 100644 --- a/src/nm-l3cfg.c +++ b/src/core/nm-l3cfg.c @@ -1,28 +1,33 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-l3cfg.h" #include <net/if.h> #include <linux/if_addr.h> +#include <linux/if_ether.h> #include <linux/rtnetlink.h> #include "platform/nm-platform.h" #include "platform/nmp-object.h" #include "nm-netns.h" #include "n-acd/src/n-acd.h" +#include "nm-l3-ipv4ll.h" /*****************************************************************************/ +G_STATIC_ASSERT(NM_ACD_TIMEOUT_RFC5227_MSEC == N_ACD_TIMEOUT_RFC5227); + #define ACD_SUPPORTED_ETH_ALEN ETH_ALEN #define ACD_ENSURE_RATELIMIT_MSEC ((guint32) 4000u) #define ACD_WAIT_PROBING_EXTRA_TIME_MSEC ((guint32)(1000u + ACD_ENSURE_RATELIMIT_MSEC)) #define ACD_WAIT_PROBING_EXTRA_TIME2_MSEC ((guint32) 1000u) -#define ACD_WAIT_PROBING_RESTART_TIME_MSEC ((guint32) 8000u) #define ACD_MAX_TIMEOUT_MSEC ((guint32) 30000u) #define ACD_WAIT_TIME_PROBING_FULL_RESTART_MSEC ((guint32) 30000u) -#define ACD_WAIT_TIME_ANNOUNCE_RESTART_MSEC ((guint32) 20000u) +#define ACD_WAIT_TIME_CONFLICT_RESTART_MSEC ((guint32) 120000u) +#define ACD_WAIT_TIME_ANNOUNCE_RESTART_MSEC ((guint32) 30000u) +#define ACD_DEFENDCONFLICT_INFO_RATELIMIT_MSEC ((guint32) 30000u) static gboolean ACD_ADDR_SKIP(in_addr_t addr) @@ -39,13 +44,16 @@ ACD_ADDR_SKIP(in_addr_t addr) ACD_TRACK_PTR2((acd_track)->l3cd, (acd_track)->obj, (acd_track)->tag) typedef enum { - ACD_STATE_CHANGE_MODE_INIT, + ACD_STATE_CHANGE_MODE_NACD_CONFLICT = N_ACD_EVENT_CONFLICT, + ACD_STATE_CHANGE_MODE_NACD_DEFENDED = N_ACD_EVENT_DEFENDED, + ACD_STATE_CHANGE_MODE_NACD_DOWN = N_ACD_EVENT_DOWN, + ACD_STATE_CHANGE_MODE_NACD_READY = N_ACD_EVENT_READY, + ACD_STATE_CHANGE_MODE_NACD_USED = N_ACD_EVENT_USED, + + ACD_STATE_CHANGE_MODE_INIT = _N_ACD_EVENT_N, + ACD_STATE_CHANGE_MODE_INIT_REAPPLY, ACD_STATE_CHANGE_MODE_POST_COMMIT, - ACD_STATE_CHANGE_MODE_NACD_READY, - ACD_STATE_CHANGE_MODE_NACD_USED, - ACD_STATE_CHANGE_MODE_NACD_DOWN, - ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED, ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED, ACD_STATE_CHANGE_MODE_LINK_NOW_UP, @@ -53,57 +61,41 @@ typedef enum { ACD_STATE_CHANGE_MODE_TIMEOUT, } AcdStateChangeMode; -typedef struct { - CList acd_track_lst; - const NMPObject * obj; - const NML3ConfigData *l3cd; - gconstpointer tag; - guint32 acd_timeout_msec; - bool acd_dirty : 1; - bool acd_failed_notified : 1; -} AcdTrackData; - -typedef enum _nm_packed { - ACD_STATE_INIT, - ACD_STATE_PROBING, - ACD_STATE_PROBE_DONE, - ACD_STATE_ANNOUNCING, -} AcdState; +G_STATIC_ASSERT(G_STRUCT_OFFSET(NML3AcdAddrInfo, addr) == 0); typedef struct { - in_addr_t addr; - - /* This is only relevant while in state ACD_STATE_PROBING. It's the - * duration for how long we probe, and @probing_timestamp_msec is the - * timestamp when we start probing. */ - guint32 probing_timeout_msec; + NML3AcdAddrInfo info; CList acd_lst; - CList acd_notify_complete_lst; - CList acd_track_lst_head; - - NML3Cfg *self; + CList acd_event_notify_lst; NAcdProbe *nacd_probe; - GSource *acd_timeout_source; - gint64 acd_timeout_expiry_msec; + GSource *acd_data_timeout_source; /* see probing_timeout_msec. */ gint64 probing_timestamp_msec; - /* the ACD state for this address. */ - AcdState acd_state; + gint64 last_defendconflict_timestamp_msec; + + guint n_track_infos_alloc; + + /* This is only relevant while in state NM_L3_ACD_ADDR_STATE_PROBING. It's the + * duration for how long we probe, and @probing_timestamp_msec is the + * timestamp when we start probing. */ + guint32 probing_timeout_msec; - /* The probe result. This is only relevant if @acd_state is ACD_STATE_PROBE_DONE. - * In state ACD_STATE_ANNOUNCING the @probe_result must be TRUE. */ - bool probe_result : 1; + NMEtherAddr last_conflict_addr; - bool announcing_failed_is_retrying : 1; + NML3AcdDefendType acd_defend_type_desired : 3; + NML3AcdDefendType acd_defend_type_current : 3; + bool acd_defend_type_is_active : 1; - bool initializing : 1; + bool track_infos_changed : 1; } AcdData; +G_STATIC_ASSERT(G_STRUCT_OFFSET(AcdData, info.addr) == 0); + struct _NML3CfgCommitTypeHandle { CList commit_type_lst; NML3CfgCommitType commit_type; @@ -133,11 +125,12 @@ typedef struct { }; guint32 default_route_penalty_x[2]; }; - gconstpointer tag; - guint64 pseudo_timestamp; - int priority; - guint32 acd_timeout_msec; - bool dirty : 1; + gconstpointer tag_confdata; + guint64 pseudo_timestamp_confdata; + int priority_confdata; + guint32 acd_timeout_msec_confdata; + NML3AcdDefendType acd_defend_type_confdata : 3; + bool dirty_confdata : 1; } L3ConfigData; /*****************************************************************************/ @@ -155,6 +148,8 @@ typedef struct _NML3CfgPrivate { GArray *property_emit_list; GArray *l3_config_datas; + NML3IPv4LL *ipv4ll; + const NML3ConfigData *combined_l3cd_merged; const NML3ConfigData *combined_l3cd_commited; @@ -170,11 +165,14 @@ typedef struct _NML3CfgPrivate { GHashTable *acd_lst_hash; CList acd_lst_head; - CList acd_notify_complete_lst_head; + CList acd_event_notify_lst_head; NAcd * nacd; GSource *nacd_source; + GSource *nacd_event_down_source; + gint64 nacd_event_down_ratelimited_until_msec; + /* This is for rate-limiting the creation of nacd instance. */ GSource *nacd_instance_ensure_retry; @@ -198,16 +196,35 @@ typedef struct _NML3CfgPrivate { guint externally_removed_objs_cnt_routes_x[2]; }; + union { + struct { + GPtrArray *last_addresses_6; + GPtrArray *last_addresses_4; + }; + GPtrArray *last_addresses_x[2]; + }; + + union { + struct { + GPtrArray *last_routes_6; + GPtrArray *last_routes_4; + }; + GPtrArray *last_routes_x[2]; + }; + guint routes_temporary_not_available_id; + gint8 commit_reentrant_count; + bool commit_type_update_sticky : 1; bool acd_is_pending : 1; - bool acd_is_announcing : 1; bool nacd_acd_not_supported : 1; bool acd_ipv4_addresses_on_link_has : 1; + bool changed_configs_configs : 1; + bool changed_configs_acd_state : 1; } NML3CfgPrivate; struct _NML3CfgClass { @@ -234,15 +251,16 @@ G_DEFINE_TYPE(NML3Cfg, nm_l3cfg, G_TYPE_OBJECT) } \ G_STMT_END -#define _LOGT_acd(acd_data, ...) \ - G_STMT_START \ - { \ - char _sbuf_acd[NM_UTILS_INET_ADDRSTRLEN]; \ - \ - _LOGT("acd[%s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _nm_utils_inet4_ntop((acd_data)->addr, _sbuf_acd) \ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ +#define _LOGT_acd(acd_data, ...) \ + G_STMT_START \ + { \ + char _sbuf_acd[NM_UTILS_INET_ADDRSTRLEN]; \ + \ + _LOGT("acd[%s, %s]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _nm_utils_inet4_ntop((acd_data)->info.addr, _sbuf_acd), \ + _l3_acd_addr_state_to_string((acd_data)->info.state) \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ G_STMT_END /*****************************************************************************/ @@ -251,7 +269,7 @@ static void _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is static void _property_emit_notify(NML3Cfg *self, NML3CfgPropertyEmitType emit_type); -static void _l3_acd_data_notify_acd_completed_all(NML3Cfg *self); +static void _nm_l3cfg_emit_signal_notify_acd_event_all(NML3Cfg *self); static gboolean _acd_has_valid_link(const NMPObject *obj, const guint8 ** out_addr_bin, @@ -260,12 +278,11 @@ static gboolean _acd_has_valid_link(const NMPObject *obj, static void _l3_acd_nacd_instance_reset(NML3Cfg *self, NMTernary start_timer, gboolean acd_data_notify); -static void _l3_acd_data_prune(NML3Cfg *self, gboolean all); - static void _l3_acd_data_state_change(NML3Cfg * self, AcdData * acd_data, AcdStateChangeMode mode, - NAcdEvent * event); + const NMEtherAddr *sender, + gint64 * p_now_msec); static AcdData *_l3_acd_data_find(NML3Cfg *self, in_addr_t addr); @@ -282,7 +299,8 @@ static NM_UTILS_ENUM2STR_DEFINE(_l3_cfg_commit_type_to_string, static NM_UTILS_ENUM2STR_DEFINE( _l3_config_notify_type_to_string, NML3ConfigNotifyType, - NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED, "acd-complete"), + NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT, "acd-event"), + NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT, "ipv4ll-event"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, "platform-change"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, "platform-change-on-idle"), NM_UTILS_ENUM2STR(NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, "post-commit"), @@ -290,6 +308,36 @@ static NM_UTILS_ENUM2STR_DEFINE( "routes-temporary-not-available-expired"), NM_UTILS_ENUM2STR_IGNORE(_NM_L3_CONFIG_NOTIFY_TYPE_NUM), ); +static NM_UTILS_ENUM2STR_DEFINE(_l3_acd_defend_type_to_string, + NML3AcdDefendType, + NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_ALWAYS, "always"), + NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_NEVER, "never"), + NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_NONE, "none"), + NM_UTILS_ENUM2STR(NM_L3_ACD_DEFEND_TYPE_ONCE, "once"), ); + +static NM_UTILS_LOOKUP_DEFINE(_l3_acd_defend_type_to_nacd, + NML3AcdDefendType, + int, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(0), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_DEFEND_TYPE_ALWAYS, + N_ACD_DEFEND_ALWAYS), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_DEFEND_TYPE_ONCE, N_ACD_DEFEND_ONCE), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_DEFEND_TYPE_NEVER, N_ACD_DEFEND_NEVER), + NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER(), ); + +static NM_UTILS_LOOKUP_DEFINE(_l3_acd_addr_state_to_string, + NML3AcdAddrState, + const char *, + NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(NULL), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_CONFLICT, "conflict"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_READY, "ready"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_DEFENDING, "defending"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_INIT, "init"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_PROBING, "probing"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED, + "external-removed"), + NM_UTILS_LOOKUP_ITEM(NM_L3_ACD_ADDR_STATE_USED, "used"), ); + /*****************************************************************************/ static const char * @@ -297,9 +345,11 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, char * sbuf, gsize sbuf_size) { - char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; - char *s = sbuf; - gsize l = sbuf_size; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + char sbuf100[100]; + char * s = sbuf; + gsize l = sbuf_size; + in_addr_t addr4; nm_assert(sbuf); nm_assert(sbuf_size > 0); @@ -308,12 +358,12 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, nm_utils_strbuf_seek_end(&s, &l); switch (notify_data->notify_type) { - case NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED: + case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT: nm_utils_strbuf_append(&s, &l, - ", addr=%s, probe-result=%d", - _nm_utils_inet4_ntop(notify_data->acd_completed.addr, sbuf_addr), - (int) notify_data->acd_completed.probe_result); + ", addr=%s, state=%s", + _nm_utils_inet4_ntop(notify_data->acd_event.info.addr, sbuf_addr), + _l3_acd_addr_state_to_string(notify_data->acd_event.info.state)); break; case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE: nm_utils_strbuf_append( @@ -330,6 +380,19 @@ _l3_config_notify_data_to_string(const NML3ConfigNotifyData *notify_data, ", obj-type-flags=0x%x", notify_data->platform_change_on_idle.obj_type_flags); break; + case NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT: + nm_assert(NM_IS_L3_IPV4LL(notify_data->ipv4ll_event.ipv4ll)); + addr4 = nm_l3_ipv4ll_get_addr(notify_data->ipv4ll_event.ipv4ll); + nm_utils_strbuf_append( + &s, + &l, + ", ipv4ll=" NM_HASH_OBFUSCATE_PTR_FMT "%s%s, state=%s", + NM_HASH_OBFUSCATE_PTR(notify_data->ipv4ll_event.ipv4ll), + NM_PRINT_FMT_QUOTED2(addr4 != 0, ", addr=", _nm_utils_inet4_ntop(addr4, sbuf_addr), ""), + nm_l3_ipv4ll_state_to_string(nm_l3_ipv4ll_get_state(notify_data->ipv4ll_event.ipv4ll), + sbuf100, + sizeof(sbuf100))); + break; default: break; } @@ -365,8 +428,9 @@ _nm_l3cfg_emit_signal_notify_simple(NML3Cfg *self, NML3ConfigNotifyType notify_t static void _l3_changed_configs_set_dirty(NML3Cfg *self) { - _LOGT("configuration changed"); - self->priv.changed_configs = TRUE; + _LOGT("IP configuration changed (mark dirty)"); + self->priv.p->changed_configs_configs = TRUE; + self->priv.p->changed_configs_acd_state = TRUE; } /*****************************************************************************/ @@ -386,7 +450,11 @@ _l3_acd_ipv4_addresses_on_link_update(NML3Cfg * self, else self->priv.p->acd_ipv4_addresses_on_link_has = FALSE; if (acd_data) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED, NULL); + _l3_acd_data_state_change(self, + acd_data, + ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED, + NULL, + NULL); return; } @@ -396,8 +464,13 @@ _l3_acd_ipv4_addresses_on_link_update(NML3Cfg * self, * cached addresses, and fetch them new the next time we need the information. */ nm_clear_pointer(&self->priv.p->acd_ipv4_addresses_on_link, g_hash_table_unref); self->priv.p->acd_ipv4_addresses_on_link_has = FALSE; - if (acd_data) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED, NULL); + if (acd_data) { + _l3_acd_data_state_change(self, + acd_data, + ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED, + NULL, + NULL); + } } static gboolean @@ -499,15 +572,15 @@ _l3cfg_externally_removed_objs_drop_unused(NML3Cfg *self) g_hash_table_iter_init(&h_iter, self->priv.p->externally_removed_objs_hash); while (g_hash_table_iter_next(&h_iter, (gpointer *) &obj, NULL)) { - if (!nm_l3_config_data_lookup_route_obj(self->priv.p->combined_l3cd_commited, obj)) { + if (!nm_l3_config_data_lookup_obj(self->priv.p->combined_l3cd_commited, obj)) { /* The object is no longer tracked in the configuration. * The externally_removed_objs_hash is to prevent adding entires that were * removed externally, so if we don't plan to add the entry, we no longer need to track * it. */ - (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj))))--; - g_hash_table_iter_remove(&h_iter); _LOGD("externally-removed: untrack %s", nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); + (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj))))--; + g_hash_table_iter_remove(&h_iter); } } } @@ -525,10 +598,17 @@ _l3cfg_externally_removed_objs_track(NML3Cfg *self, const NMPObject *obj, gboole if (!is_removed) { /* the object is still (or again) present. It no longer gets hidden. */ if (self->priv.p->externally_removed_objs_hash) { - if (g_hash_table_remove(self->priv.p->externally_removed_objs_hash, obj)) { - (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj))))--; + const NMPObject *obj2; + gpointer x_val; + + if (g_hash_table_steal_extended(self->priv.p->externally_removed_objs_hash, + obj, + (gpointer *) &obj2, + &x_val)) { + (*(_l3cfg_externally_removed_objs_counter(self, NMP_OBJECT_GET_TYPE(obj2))))--; _LOGD("externally-removed: untrack %s", - nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); + nmp_object_to_string(obj2, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf))); + nmp_object_unref(obj2); } } return; @@ -558,26 +638,24 @@ _l3cfg_externally_removed_objs_track(NML3Cfg *self, const NMPObject *obj, gboole static void _l3cfg_externally_removed_objs_pickup(NML3Cfg *self, int addr_family) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); NMDedupMultiIter iter; const NMPObject *obj; if (!self->priv.p->combined_l3cd_commited) return; - nm_l3_config_data_iter_obj_for_each(&iter, - self->priv.p->combined_l3cd_commited, - &obj, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + self->priv.p->combined_l3cd_commited, + &obj, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)) { if (!nm_platform_lookup_entry(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)) _l3cfg_externally_removed_objs_track(self, obj, TRUE); } - nm_l3_config_data_iter_obj_for_each(&iter, - self->priv.p->combined_l3cd_commited, - &obj, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) - { + nm_l3_config_data_iter_obj_for_each (&iter, + self->priv.p->combined_l3cd_commited, + &obj, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)) { if (!nm_platform_lookup_entry(self->priv.platform, NMP_CACHE_ID_TYPE_OBJECT_TYPE, obj)) _l3cfg_externally_removed_objs_track(self, obj, TRUE); } @@ -590,7 +668,11 @@ _l3cfg_externally_removed_objs_filter(/* const NMDedupMultiObj * */ gconstpointe const NMPObject *obj = o; GHashTable * externally_removed_objs_hash = user_data; - return !g_hash_table_contains(externally_removed_objs_hash, obj); + if (NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_IP4_ADDRESS + && NMP_OBJECT_CAST_IP4_ADDRESS(obj)->ip4acd_not_ready) + return FALSE; + + return !nm_g_hash_table_contains(externally_removed_objs_hash, obj); } /*****************************************************************************/ @@ -664,9 +746,16 @@ _load_link(NML3Cfg *self, gboolean initial) _l3_acd_nacd_instance_reset(self, NM_TERNARY_FALSE, TRUE); } else if (nacd_link_now_up) { if (!c_list_is_empty(&self->priv.p->acd_lst_head)) { + gint64 now_msec = 0; + _LOGT("acd: link up requires are re-initialize of ACD probes"); - c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_LINK_NOW_UP, NULL); + c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) { + _l3_acd_data_state_change(self, + acd_data, + ACD_STATE_CHANGE_MODE_LINK_NOW_UP, + NULL, + &now_msec); + } } } } @@ -687,7 +776,7 @@ _nm_l3cfg_notify_platform_change_on_idle(NML3Cfg *self, guint32 obj_type_flags) }; _nm_l3cfg_emit_signal_notify(self, ¬ify_data); - _l3_acd_data_notify_acd_completed_all(self); + _nm_l3cfg_emit_signal_notify_acd_event_all(self); if (NM_FLAGS_ANY(obj_type_flags, nmp_object_type_to_flags(NMP_OBJECT_TYPE_IP4_ROUTE))) _property_emit_notify(self, NM_L3CFG_PROPERTY_EMIT_TYPE_IP4_ROUTE); @@ -891,84 +980,77 @@ nm_l3cfg_get_acd_is_pending(NML3Cfg *self) } static gboolean -_acd_track_data_is_not_dirty(const AcdTrackData *acd_track) +_acd_track_data_is_not_dirty(const NML3AcdAddrTrackInfo *acd_track) { - return acd_track && !acd_track->acd_dirty; + return acd_track && !acd_track->_priv.acd_dirty_track; } static void -_acd_track_data_free(AcdTrackData *acd_track) +_acd_track_data_clear(NML3AcdAddrTrackInfo *acd_track) { - c_list_unlink_stale(&acd_track->acd_track_lst); nm_l3_config_data_unref(acd_track->l3cd); nmp_object_unref(acd_track->obj); - nm_g_slice_free(acd_track); } static void _acd_data_free(AcdData *acd_data) { - nm_assert(c_list_is_empty(&acd_data->acd_track_lst_head)); + nm_assert(acd_data->info.n_track_infos == 0u); n_acd_probe_free(acd_data->nacd_probe); - nm_clear_g_source_inst(&acd_data->acd_timeout_source); + nm_clear_g_source_inst(&acd_data->acd_data_timeout_source); c_list_unlink_stale(&acd_data->acd_lst); + c_list_unlink_stale(&acd_data->acd_event_notify_lst); + g_free((NML3AcdAddrTrackInfo *) acd_data->info.track_infos); nm_g_slice_free(acd_data); } -static gboolean -_acd_data_probe_result_is_good(const AcdData *acd_data) -{ - nm_assert(acd_data); - - if (acd_data->acd_state < ACD_STATE_PROBE_DONE) { - /* we are currently probing. Wait. */ - return FALSE; - } - - /* Probing is already completed. Use the probe result. */ - return acd_data->probe_result; -} - static guint -_acd_data_collect_tracks_data(const AcdData *acd_data, - NMTernary dirty_selector, - NMTernary acd_failed_notified_selector, - guint32 * out_best_acd_timeout_msec) -{ - guint32 best_acd_timeout_msec = G_MAXUINT32; - AcdTrackData *acd_track; - guint n = 0; +_acd_data_collect_tracks_data(const AcdData * acd_data, + NMTernary dirty_selector, + guint32 * out_best_acd_timeout_msec, + NML3AcdDefendType *out_best_acd_defend_type) +{ + NML3AcdDefendType best_acd_defend_type = NM_L3_ACD_DEFEND_TYPE_NONE; + guint32 best_acd_timeout_msec = G_MAXUINT32; + guint n = 0; + guint i; + + for (i = 0; i < acd_data->info.n_track_infos; i++) { + const NML3AcdAddrTrackInfo *acd_track = &acd_data->info.track_infos[i]; - c_list_for_each_entry (acd_track, &acd_data->acd_track_lst_head, acd_track_lst) { if (dirty_selector != NM_TERNARY_DEFAULT) { - if ((!!dirty_selector) != (!!acd_track->acd_dirty)) - continue; - } - if (acd_failed_notified_selector != NM_TERNARY_DEFAULT) { - if ((!!acd_failed_notified_selector) != (!!acd_track->acd_failed_notified)) + if ((!!dirty_selector) != (!!acd_track->_priv.acd_dirty_track)) continue; } n++; - if (best_acd_timeout_msec > acd_track->acd_timeout_msec) - best_acd_timeout_msec = acd_track->acd_timeout_msec; + if (best_acd_timeout_msec > acd_track->_priv.acd_timeout_msec_track) + best_acd_timeout_msec = acd_track->_priv.acd_timeout_msec_track; + if (best_acd_defend_type < acd_track->_priv.acd_defend_type_track) + best_acd_defend_type = acd_track->_priv.acd_defend_type_track; } + nm_assert(n == 0 || best_acd_defend_type > NM_L3_ACD_DEFEND_TYPE_NONE); + nm_assert(best_acd_defend_type <= NM_L3_ACD_DEFEND_TYPE_ALWAYS); + NM_SET_OUT(out_best_acd_timeout_msec, n > 0 ? best_acd_timeout_msec : 0u); + NM_SET_OUT(out_best_acd_defend_type, best_acd_defend_type); return n; } -static AcdTrackData * +static NML3AcdAddrTrackInfo * _acd_data_find_track(const AcdData * acd_data, const NML3ConfigData *l3cd, const NMPObject * obj, gconstpointer tag) { - AcdTrackData *acd_track; + guint i; + + for (i = 0; i < acd_data->info.n_track_infos; i++) { + const NML3AcdAddrTrackInfo *acd_track = &acd_data->info.track_infos[i]; - c_list_for_each_entry (acd_track, &acd_data->acd_track_lst_head, acd_track_lst) { if (acd_track->obj == obj && acd_track->l3cd == l3cd && acd_track->tag == tag) - return acd_track; + return (NML3AcdAddrTrackInfo *) acd_track; } return NULL; @@ -993,7 +1075,7 @@ _acd_has_valid_link(const NMPObject *obj, link = NMP_OBJECT_CAST_LINK(obj); addr_bin = nmp_link_address_get(&link->l_address, &addr_len); - if (!addr_bin || addr_len != ACD_SUPPORTED_ETH_ALEN) { + if (addr_len != ACD_SUPPORTED_ETH_ALEN) { NM_SET_OUT(out_acd_not_supported, TRUE); return FALSE; } @@ -1004,6 +1086,21 @@ _acd_has_valid_link(const NMPObject *obj, } static gboolean +_l3_acd_nacd_event_down_timeout_cb(gpointer user_data) +{ + NML3Cfg *self = user_data; + AcdData *acd_data; + gint64 now_msec = 0; + + _LOGT("acd: message possibly dropped due to device down (handle events)"); + nm_clear_g_source_inst(&self->priv.p->nacd_event_down_source); + c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) + _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_NACD_DOWN, NULL, &now_msec); + _nm_l3cfg_emit_signal_notify_acd_event_all(self); + return G_SOURCE_REMOVE; +} + +static gboolean _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) { NML3Cfg *self = user_data; @@ -1020,8 +1117,10 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) } while (TRUE) { - AcdData * acd_data; - NAcdEvent *event; + NMEtherAddr sender_addr_data; + const NMEtherAddr *sender_addr; + AcdData * acd_data; + NAcdEvent * event; r = n_acd_pop_event(self->priv.p->nacd, &event); if (r) { @@ -1033,77 +1132,83 @@ _l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) goto out; } -#define _acd_event_payload used - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NAcdEvent, _acd_event_payload) - == G_STRUCT_OFFSET(NAcdEvent, defended)); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NAcdEvent, _acd_event_payload) - == G_STRUCT_OFFSET(NAcdEvent, conflict)); - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NAcdEvent, _acd_event_payload) - == G_STRUCT_OFFSET(NAcdEvent, used)); - nm_assert(&event->_acd_event_payload == &event->defended); - nm_assert(&event->_acd_event_payload == &event->conflict); - nm_assert(&event->_acd_event_payload == &event->used); - switch (event->event) { case N_ACD_EVENT_READY: - n_acd_probe_get_userdata(event->_acd_event_payload.probe, (void **) &acd_data); - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_NACD_READY, event); + n_acd_probe_get_userdata(event->ready.probe, (void **) &acd_data); + _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_NACD_READY, NULL, NULL); break; case N_ACD_EVENT_USED: - n_acd_probe_get_userdata(event->_acd_event_payload.probe, (void **) &acd_data); - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_NACD_USED, event); - break; case N_ACD_EVENT_DEFENDED: case N_ACD_EVENT_CONFLICT: { - gs_free char *sender_str = NULL; - const char * addr_str = NULL; - char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; - - /* since we announce with N_ACD_DEFEND_ALWAYS, we don't actually expect any - * conflict reported and don't handle it. It would be complicated to de-configure - * the address. */ - nm_assert(event->event == N_ACD_EVENT_DEFENDED); - - n_acd_probe_get_userdata(event->_acd_event_payload.probe, (void **) &acd_data); - _LOGT_acd(acd_data, - "address %s %s from %s", - (addr_str = _nm_utils_inet4_ntop(acd_data->addr, sbuf_addr)), - event->event == N_ACD_EVENT_DEFENDED ? "defended" : "conflict detected", - (sender_str = nm_utils_bin2hexstr_full(event->_acd_event_payload.sender, - event->_acd_event_payload.n_sender, - ':', - FALSE, - NULL))); - if (event->event == N_ACD_EVENT_CONFLICT) { - _LOGW("IPv4 address collision detection sees conflict on interface %i%s%s%s for " - "address %s from host %s", - self->priv.ifindex, - NM_PRINT_FMT_QUOTED(self->priv.plobj, - " (", - NMP_OBJECT_CAST_LINK(self->priv.plobj)->name, - ")", - ""), - addr_str ?: _nm_utils_inet4_ntop(acd_data->addr, sbuf_addr), - sender_str - ?: (sender_str = - nm_utils_bin2hexstr_full(event->_acd_event_payload.sender, - event->_acd_event_payload.n_sender, - ':', - FALSE, - NULL))); +#define _acd_event_payload_with_sender(event) \ + ({ \ + NAcdEvent *_event = (event); \ + \ + nm_assert(event); \ + nm_assert(NM_IN_SET(event->event, \ + N_ACD_EVENT_USED, \ + N_ACD_EVENT_DEFENDED, \ + N_ACD_EVENT_CONFLICT)); \ + nm_assert(&_event->used == &_event->defended); \ + nm_assert(&_event->used == &_event->conflict); \ + &_event->used; \ + }) + + n_acd_probe_get_userdata(_acd_event_payload_with_sender(event)->probe, + (void **) &acd_data); + + if (_acd_event_payload_with_sender(event)->n_sender == ETH_ALEN) { + G_STATIC_ASSERT_EXPR(_nm_alignof(NMEtherAddr) == 1); + nm_assert(_acd_event_payload_with_sender(event)->sender); + memcpy(&sender_addr_data, _acd_event_payload_with_sender(event)->sender, ETH_ALEN); + sender_addr = &sender_addr_data; + } else { + nm_assert_not_reached(); + sender_addr = &nm_ether_addr_zero; } + + _l3_acd_data_state_change(self, + acd_data, + (AcdStateChangeMode) event->event, + sender_addr, + NULL); break; } case N_ACD_EVENT_DOWN: - _LOGT("acd: message possibly dropped due to device down."); - c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_NACD_DOWN, NULL); + if (!self->priv.p->nacd_event_down_source) { + gint64 now_msec; + guint32 timeout_msec; + + now_msec = nm_utils_get_monotonic_timestamp_msec(); + if (self->priv.p->nacd_event_down_ratelimited_until_msec > 0 + && now_msec < self->priv.p->nacd_event_down_ratelimited_until_msec) + timeout_msec = self->priv.p->nacd_event_down_ratelimited_until_msec - now_msec; + else { + timeout_msec = 0; + self->priv.p->nacd_event_down_ratelimited_until_msec = now_msec + 2000; + } + _LOGT("acd: message possibly dropped due to device down (schedule handling event " + "in %u msec)", + timeout_msec); + self->priv.p->nacd_event_down_source = + nm_g_timeout_source_new(timeout_msec, + G_PRIORITY_DEFAULT, + _l3_acd_nacd_event_down_timeout_cb, + self, + NULL); + g_source_attach(self->priv.p->nacd_event_down_source, NULL); + } break; default: - _LOGT("acd: unexpected event %u. Ignore", event->event); + _LOGE("acd: unexpected event %u. Ignore", event->event); + nm_assert_not_reached(); break; } + + /* We are on an idle handler, and the n-acd events are expected to be independent. So, after + * each event emit all queued AcdEvent signals. */ + _nm_l3cfg_emit_signal_notify_acd_event_all(self); } nm_assert_not_reached(); @@ -1115,8 +1220,6 @@ out: _l3_acd_nacd_instance_reset(self, NM_TERNARY_TRUE, TRUE); } - _l3_acd_data_notify_acd_completed_all(self); - return G_SOURCE_CONTINUE; } @@ -1167,9 +1270,15 @@ _l3_acd_nacd_instance_reset(NML3Cfg *self, NMTernary start_timer, gboolean acd_d if (acd_data_notify) { AcdData *acd_data; - - c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_INSTANCE_RESET, NULL); + gint64 now_msec = 0; + + c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) { + _l3_acd_data_state_change(self, + acd_data, + ACD_STATE_CHANGE_MODE_INSTANCE_RESET, + NULL, + &now_msec); + } } } @@ -1275,30 +1384,37 @@ _l3_acd_nacd_instance_create_probe(NML3Cfg * self, } static void -_l3_acd_data_free_trackers(NML3Cfg *self, AcdData *acd_data, gboolean all /* or only dirty */) +_l3_acd_data_prune_one(NML3Cfg *self, AcdData *acd_data, gboolean all /* or only dirty */) { - AcdTrackData *acd_track; - AcdTrackData *acd_track_safe; + NML3AcdAddrTrackInfo *acd_tracks; + guint i; + guint j; + + acd_tracks = (NML3AcdAddrTrackInfo *) acd_data->info.track_infos; + j = 0; + for (i = 0; i < acd_data->info.n_track_infos; i++) { + NML3AcdAddrTrackInfo *acd_track = &acd_tracks[i]; - c_list_for_each_entry_safe (acd_track, - acd_track_safe, - &acd_data->acd_track_lst_head, - acd_track_lst) { /* If not "all" is requested, we only delete the dirty ones * (and mark the survivors as dirty right away). */ - if (!all && !acd_track->acd_dirty) { - acd_track->acd_dirty = TRUE; + if (!all && !acd_track->_priv.acd_dirty_track) { + acd_track->_priv.acd_dirty_track = TRUE; + if (j != i) + acd_tracks[j] = *acd_track; + j++; continue; } _LOGT_acd(acd_data, "untrack " ACD_TRACK_FMT "", ACD_TRACK_PTR(acd_track)); - _acd_track_data_free(acd_track); + _acd_track_data_clear(acd_track); } - if (!c_list_is_empty(&acd_data->acd_track_lst_head)) + acd_data->info.n_track_infos = j; + if (j > 0) return; + _LOGT_acd(acd_data, "removed"); if (!g_hash_table_remove(self->priv.p->acd_lst_hash, acd_data)) nm_assert_not_reached(); _acd_data_free(acd_data); @@ -1311,7 +1427,7 @@ _l3_acd_data_prune(NML3Cfg *self, gboolean all /* or only dirty */) AcdData *acd_data; c_list_for_each_entry_safe (acd_data, acd_data_safe, &self->priv.p->acd_lst_head, acd_lst) - _l3_acd_data_free_trackers(self, acd_data, all); + _l3_acd_data_prune_one(self, acd_data, all); } static AcdData * @@ -1320,17 +1436,33 @@ _l3_acd_data_find(NML3Cfg *self, in_addr_t addr) return nm_g_hash_table_lookup(self->priv.p->acd_lst_hash, &addr); } +static gboolean +_l3_acd_data_defendconflict_warning_ratelimited(AcdData *acd_data, gint64 *p_now_msec) +{ + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); + + if (acd_data->last_defendconflict_timestamp_msec == 0 + || acd_data->last_defendconflict_timestamp_msec + > *p_now_msec - ACD_DEFENDCONFLICT_INFO_RATELIMIT_MSEC) { + acd_data->last_defendconflict_timestamp_msec = *p_now_msec; + return FALSE; + } + return TRUE; +} + static void _l3_acd_data_add(NML3Cfg * self, const NML3ConfigData *l3cd, const NMPObject * obj, gconstpointer tag, + NML3AcdDefendType acd_defend_type, guint32 acd_timeout_msec) { - in_addr_t addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address; - AcdTrackData *acd_track; - AcdData * acd_data; - const char * track_mode; + in_addr_t addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address; + NML3AcdAddrTrackInfo *acd_track; + AcdData * acd_data; + const char * track_mode; + char sbuf100[100]; if (ACD_ADDR_SKIP(addr)) return; @@ -1345,64 +1477,93 @@ _l3_acd_data_add(NML3Cfg * self, if (!acd_data) { if (G_UNLIKELY(!self->priv.p->acd_lst_hash)) { - G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(AcdData, addr) == 0); + G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(AcdData, info.addr) == 0); self->priv.p->acd_lst_hash = g_hash_table_new(nm_puint32_hash, nm_puint32_equals); } acd_data = g_slice_new(AcdData); *acd_data = (AcdData){ - .self = self, - .addr = addr, - .acd_track_lst_head = C_LIST_INIT(acd_data->acd_track_lst_head), - .acd_notify_complete_lst = C_LIST_INIT(acd_data->acd_notify_complete_lst), - .acd_state = ACD_STATE_INIT, - .probing_timestamp_msec = 0, - .probe_result = FALSE, - .initializing = TRUE, + .info = + { + .l3cfg = self, + .addr = addr, + .state = NM_L3_ACD_ADDR_STATE_INIT, + .n_track_infos = 0, + .track_infos = NULL, + }, + .n_track_infos_alloc = 0, + .acd_event_notify_lst = C_LIST_INIT(acd_data->acd_event_notify_lst), + .probing_timestamp_msec = 0, + .acd_defend_type_desired = NM_L3_ACD_DEFEND_TYPE_NONE, + .acd_defend_type_current = NM_L3_ACD_DEFEND_TYPE_NONE, + .acd_defend_type_is_active = FALSE, }; c_list_link_tail(&self->priv.p->acd_lst_head, &acd_data->acd_lst); if (!g_hash_table_add(self->priv.p->acd_lst_hash, acd_data)) nm_assert_not_reached(); acd_track = NULL; - } else { + } else acd_track = _acd_data_find_track(acd_data, l3cd, obj, tag); - } if (!acd_track) { - acd_track = g_slice_new(AcdTrackData); - *acd_track = (AcdTrackData){ - .l3cd = nm_l3_config_data_ref(l3cd), - .obj = nmp_object_ref(obj), - .tag = tag, - .acd_dirty = FALSE, - .acd_timeout_msec = acd_timeout_msec, + if (acd_data->info.n_track_infos >= acd_data->n_track_infos_alloc) { + acd_data->n_track_infos_alloc = NM_MAX(2u, acd_data->n_track_infos_alloc * 2u); + acd_data->info.track_infos = + g_realloc((gpointer) acd_data->info.track_infos, + acd_data->n_track_infos_alloc * sizeof(acd_data->info.track_infos[0])); + } + acd_track = + (NML3AcdAddrTrackInfo *) &acd_data->info.track_infos[acd_data->info.n_track_infos++]; + *acd_track = (NML3AcdAddrTrackInfo){ + .l3cd = nm_l3_config_data_ref(l3cd), + .obj = nmp_object_ref(obj), + .tag = tag, + ._priv.acd_dirty_track = FALSE, + ._priv.acd_defend_type_track = acd_defend_type, + ._priv.acd_timeout_msec_track = acd_timeout_msec, }; - c_list_link_tail(&acd_data->acd_track_lst_head, &acd_track->acd_track_lst); track_mode = "new"; } else { - nm_assert(acd_track->acd_dirty); - acd_track->acd_dirty = FALSE; - if (acd_track->acd_timeout_msec != acd_timeout_msec) { - acd_track->acd_timeout_msec = acd_timeout_msec; - track_mode = "update"; + nm_assert(acd_track->_priv.acd_dirty_track); + acd_track->_priv.acd_dirty_track = FALSE; + if (acd_track->_priv.acd_timeout_msec_track != acd_timeout_msec + || acd_track->_priv.acd_defend_type_track != acd_defend_type) { + acd_track->_priv.acd_defend_type_track = acd_defend_type; + acd_track->_priv.acd_timeout_msec_track = acd_timeout_msec; + track_mode = "update"; } else - track_mode = NULL; + return; } - if (track_mode) { - _LOGT_acd(acd_data, - "track " ACD_TRACK_FMT " with timeout %u msec (%s)", - ACD_TRACK_PTR(acd_track), - acd_timeout_msec, - track_mode); - } + acd_data->track_infos_changed = TRUE; + _LOGT_acd(acd_data, + "track " ACD_TRACK_FMT " with timeout %u msec, defend=%s (%s)", + ACD_TRACK_PTR(acd_track), + acd_timeout_msec, + _l3_acd_defend_type_to_string(acd_track->_priv.acd_defend_type_track, + sbuf100, + sizeof(sbuf100)), + track_mode); } static void -_l3_acd_data_add_all(NML3Cfg *self, const L3ConfigData *const *infos, guint infos_len) +_l3_acd_data_add_all(NML3Cfg * self, + const L3ConfigData *const *infos, + guint infos_len, + gboolean reapply) { AcdData *acd_data; guint i_info; + gint64 now_msec = 0; + guint i; + + if (NM_MORE_ASSERTS > 5) { + c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) { + nm_assert(acd_data->info.n_track_infos > 0u); + for (i = 0; i < acd_data->info.n_track_infos; i++) + nm_assert(acd_data->info.track_infos[i]._priv.acd_dirty_track); + } + } /* First we add/track all the relevant addresses for ACD. */ for (i_info = 0; i_info < infos_len; i_info++) { @@ -1410,63 +1571,54 @@ _l3_acd_data_add_all(NML3Cfg *self, const L3ConfigData *const *infos, guint info NMDedupMultiIter iter; const NMPObject * obj; - nm_l3_config_data_iter_obj_for_each(&iter, info->l3cd, &obj, NMP_OBJECT_TYPE_IP4_ADDRESS) - _l3_acd_data_add(self, info->l3cd, obj, info->tag, info->acd_timeout_msec); + nm_l3_config_data_iter_obj_for_each (&iter, info->l3cd, &obj, NMP_OBJECT_TYPE_IP4_ADDRESS) { + _l3_acd_data_add(self, + info->l3cd, + obj, + info->tag_confdata, + info->acd_defend_type_confdata, + info->acd_timeout_msec_confdata); + } } /* Then we do a pre-flight check, whether some of the acd_data entries can already * move forward to automatically pass ACD. That is the case if acd_timeout_msec * is zero (to disable ACD) or if the address is already configured on the * interface. */ - c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_INIT, NULL); + c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) { + _l3_acd_data_state_change(self, + acd_data, + reapply ? ACD_STATE_CHANGE_MODE_INIT_REAPPLY + : ACD_STATE_CHANGE_MODE_INIT, + NULL, + &now_msec); + } } static gboolean _l3_acd_data_timeout_cb(gpointer user_data) { AcdData *acd_data = user_data; - NML3Cfg *self = acd_data->self; + NML3Cfg *self = acd_data->info.l3cfg; nm_assert(NM_IS_L3CFG(self)); - nm_clear_g_source_inst(&acd_data->acd_timeout_source); - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_TIMEOUT, NULL); + nm_clear_g_source_inst(&acd_data->acd_data_timeout_source); + _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_TIMEOUT, NULL, NULL); return G_SOURCE_REMOVE; } static void -_l3_acd_data_timeout_schedule(AcdData *acd_data, - gint64 now_msec, - gint64 expiry_msec, - gboolean msec_granularity) +_l3_acd_data_timeout_schedule(AcdData *acd_data, gint64 timeout_msec) { - nm_assert(expiry_msec > 0); - nm_assert(now_msec > 0); - - if (acd_data->acd_timeout_source && acd_data->acd_timeout_expiry_msec == expiry_msec) - return; - - nm_clear_g_source_inst(&acd_data->acd_timeout_source); - - acd_data->acd_timeout_expiry_msec = expiry_msec; - - if (msec_granularity) { - acd_data->acd_timeout_source = nm_g_timeout_source_new(NM_MAX(0, expiry_msec - now_msec), - G_PRIORITY_DEFAULT, - _l3_acd_data_timeout_cb, - acd_data, - NULL); - } else { - acd_data->acd_timeout_source = - nm_g_timeout_source_new_seconds((NM_MAX(0, expiry_msec - now_msec) + 999) / 1000, - G_PRIORITY_DEFAULT, - _l3_acd_data_timeout_cb, - acd_data, - NULL); - } - - g_source_attach(acd_data->acd_timeout_source, NULL); + nm_clear_g_source_inst(&acd_data->acd_data_timeout_source); + acd_data->acd_data_timeout_source = + nm_g_timeout_source_new(NM_CLAMP((gint64) 0, timeout_msec, (gint64) G_MAXUINT), + G_PRIORITY_DEFAULT, + _l3_acd_data_timeout_cb, + acd_data, + NULL); + g_source_attach(acd_data->acd_data_timeout_source, NULL); } static void @@ -1477,7 +1629,7 @@ _l3_acd_data_timeout_schedule_probing_restart(AcdData *acd_data, gint64 now_msec nm_assert(acd_data); nm_assert(now_msec > 0); - nm_assert(acd_data->acd_state == ACD_STATE_PROBING); + nm_assert(acd_data->info.state == NM_L3_ACD_ADDR_STATE_PROBING); nm_assert(!acd_data->nacd_probe); nm_assert(acd_data->probing_timeout_msec > 0); nm_assert(acd_data->probing_timestamp_msec > 0); @@ -1486,152 +1638,168 @@ _l3_acd_data_timeout_schedule_probing_restart(AcdData *acd_data, gint64 now_msec timeout_msec = NM_MAX(0, expiry_msec - now_msec); - if (timeout_msec > 1000) { - /* we poll at least once per second to re-check the state. */ - timeout_msec = 1000; + if (timeout_msec > 1500) { + /* we poll at least every 1.5 seconds to re-check the state. */ + timeout_msec = 1500; } - _l3_acd_data_timeout_schedule(acd_data, now_msec, now_msec + timeout_msec, TRUE); + _l3_acd_data_timeout_schedule(acd_data, timeout_msec); } static void -_l3_acd_data_timeout_schedule_probing_full_restart(AcdData *acd_data, gint64 now_msec) +_nm_l3cfg_emit_signal_notify_acd_event(NML3Cfg *self, AcdData *acd_data) { - nm_assert(acd_data); - nm_assert(now_msec > 0); - nm_assert(acd_data->acd_state == ACD_STATE_PROBE_DONE); - nm_assert(!acd_data->probe_result); - - _l3_acd_data_timeout_schedule(acd_data, - now_msec, - now_msec + ACD_WAIT_TIME_PROBING_FULL_RESTART_MSEC, - FALSE); -} + gs_free NML3AcdAddrTrackInfo *track_infos_clone = NULL; + NML3ConfigNotifyData notify_data; + NML3AcdAddrInfo * info; + guint i; -static void -_l3_acd_data_timeout_schedule_announce_restart(AcdData *acd_data, gint64 now_msec) -{ nm_assert(acd_data); - nm_assert(now_msec > 0); - nm_assert(acd_data->acd_state == ACD_STATE_PROBE_DONE); - nm_assert(acd_data->probe_result); - - _l3_acd_data_timeout_schedule(acd_data, - now_msec, - now_msec + ACD_WAIT_TIME_ANNOUNCE_RESTART_MSEC, - FALSE); -} + nm_assert(acd_data->info.state > NM_L3_ACD_ADDR_STATE_INIT); + nm_assert(acd_data->info.n_track_infos > 0); -static void -_l3_acd_data_notify_acd_completed(NML3Cfg *self, AcdData *acd_data, gboolean force_all) -{ - gs_free NML3ConfigNotifyPayloadAcdFailedSource *sources_free = NULL; - NML3ConfigNotifyPayloadAcdFailedSource * sources = NULL; - NML3ConfigNotifyData notify_data; - AcdTrackData * acd_track; - guint i, n; - NMTernary acd_failed_notified_selector; - - nm_assert(NM_IS_L3CFG(self)); - nm_assert(acd_data); - nm_assert(_acd_data_collect_tracks_data(acd_data, FALSE, NM_TERNARY_DEFAULT, NULL) == 0); - - acd_failed_notified_selector = force_all ? NM_TERNARY_DEFAULT : FALSE; + notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT; + notify_data.acd_event = (typeof(notify_data.acd_event)){ + .info = acd_data->info, + }; - n = _acd_data_collect_tracks_data(acd_data, - NM_TERNARY_DEFAULT, - acd_failed_notified_selector, - NULL); + /* we need to clone the track-data, because the callee is allowed to add/remove + * configs. This means, the event data is stale. If you need the current + * value, look it up with nm_l3cfg_get_acd_addr_info(). */ + info = ¬ify_data.acd_event.info; + info->track_infos = nm_memdup_maybe_a(300, + info->track_infos, + info->n_track_infos * sizeof(info->track_infos[0]), + &track_infos_clone); - if (n == 0) - return; + for (i = 0; i < info->n_track_infos; i++) { + NML3AcdAddrTrackInfo *ti = (NML3AcdAddrTrackInfo *) &info->track_infos[i]; - if (!force_all) { - _LOGT_acd(acd_data, "state: acd probe failed earlier. Emit notification for new trackers"); + nmp_object_ref(ti->obj); + nm_l3_config_data_ref(ti->l3cd); } - if (n * sizeof(sources[0]) > 300) { - sources_free = g_new(NML3ConfigNotifyPayloadAcdFailedSource, n); - sources = sources_free; - } else - sources = g_newa(NML3ConfigNotifyPayloadAcdFailedSource, n); - - i = 0; - c_list_for_each_entry (acd_track, &acd_data->acd_track_lst_head, acd_track_lst) { - if (!force_all && acd_track->acd_failed_notified) { - /* already notified before. Skip. */ - continue; - } - nm_assert(i < n); - acd_track->acd_failed_notified = TRUE; - sources[i++] = (NML3ConfigNotifyPayloadAcdFailedSource){ - .obj = nmp_object_ref(acd_track->obj), - .l3cd = nm_l3_config_data_ref(acd_track->l3cd), - .tag = acd_track->tag, - }; - } - nm_assert(i == n); - - notify_data.notify_type = NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED; - notify_data.acd_completed = (typeof(notify_data.acd_completed)){ - .addr = acd_data->addr, - .probe_result = acd_data->probe_result, - .sources_len = n, - .sources = sources, - }; _nm_l3cfg_emit_signal_notify(self, ¬ify_data); - for (i = 0; i < n; i++) { - nmp_object_unref(sources[i].obj); - nm_l3_config_data_unref(sources[i].l3cd); + for (i = 0; i < info->n_track_infos; i++) { + NML3AcdAddrTrackInfo *ti = (NML3AcdAddrTrackInfo *) &info->track_infos[i]; + + nmp_object_unref(ti->obj); + nm_l3_config_data_unref(ti->l3cd); } } static void -_l3_acd_data_notify_acd_completed_queue(NML3Cfg *self, AcdData *acd_data) +_nm_l3cfg_emit_signal_notify_acd_event_queue(NML3Cfg *self, AcdData *acd_data) { - if (!c_list_is_empty(&acd_data->acd_notify_complete_lst)) { - nm_assert(c_list_contains(&self->priv.p->acd_notify_complete_lst_head, - &acd_data->acd_notify_complete_lst)); + if (!c_list_is_empty(&acd_data->acd_event_notify_lst)) { + nm_assert(c_list_contains(&self->priv.p->acd_event_notify_lst_head, + &acd_data->acd_event_notify_lst)); return; } - c_list_link_tail(&self->priv.p->acd_notify_complete_lst_head, - &acd_data->acd_notify_complete_lst); + c_list_link_tail(&self->priv.p->acd_event_notify_lst_head, &acd_data->acd_event_notify_lst); } static void -_l3_acd_data_notify_acd_completed_all(NML3Cfg *self) +_nm_l3cfg_emit_signal_notify_acd_event_all(NML3Cfg *self) { gs_unref_object NML3Cfg *self_keep_alive = NULL; AcdData * acd_data; - while ((acd_data = c_list_first_entry(&self->priv.p->acd_notify_complete_lst_head, + while ((acd_data = c_list_first_entry(&self->priv.p->acd_event_notify_lst_head, AcdData, - acd_notify_complete_lst))) { + acd_event_notify_lst))) { if (!self_keep_alive) self_keep_alive = g_object_ref(self); - c_list_unlink(&acd_data->acd_notify_complete_lst); - _l3_acd_data_notify_acd_completed(self, acd_data, TRUE); + c_list_unlink(&acd_data->acd_event_notify_lst); + _nm_l3cfg_emit_signal_notify_acd_event(self, acd_data); } } +_nm_printf(5, 6) static void _l3_acd_data_state_set_full(NML3Cfg * self, + AcdData * acd_data, + NML3AcdAddrState state, + gboolean allow_commit, + const char * format, + ...) +{ + NML3AcdAddrState old_state; + gboolean changed; + + if (acd_data->info.state == state) + return; + + /* in every state we only have one timer possibly running. Resetting + * the states makes the previous timeout obsolete. */ + nm_clear_g_source_inst(&acd_data->acd_data_timeout_source); + + old_state = acd_data->info.state; + acd_data->info.state = state; + _nm_l3cfg_emit_signal_notify_acd_event_queue(self, acd_data); + + if (state == NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED) + changed = FALSE; + else if (NM_IN_SET(old_state, NM_L3_ACD_ADDR_STATE_READY, NM_L3_ACD_ADDR_STATE_DEFENDING) + != NM_IN_SET(state, NM_L3_ACD_ADDR_STATE_READY, NM_L3_ACD_ADDR_STATE_DEFENDING)) + changed = TRUE; + else + changed = FALSE; + + if (format) { + gs_free char *msg = NULL; + va_list args; + + va_start(args, format); + msg = g_strdup_vprintf(format, args); + va_end(args); + + _LOGT_acd(acd_data, "set state to %s (%s)", _l3_acd_addr_state_to_string(state), msg); + } else + _LOGT_acd(acd_data, "set state to %s", _l3_acd_addr_state_to_string(state)); + + if (changed && allow_commit) { + /* The availability of an address just changed (and we are instructed to + * trigger a new commit). Do it. */ + _l3_changed_configs_set_dirty(self); + nm_l3cfg_commit_on_idle_schedule(self); + } +} + +static void +_l3_acd_data_state_set(NML3Cfg * self, + AcdData * acd_data, + NML3AcdAddrState state, + gboolean allow_commit) +{ + _l3_acd_data_state_set_full(self, acd_data, state, allow_commit, NULL); +} + static void _l3_acd_data_state_change(NML3Cfg * self, AcdData * acd_data, AcdStateChangeMode state_change_mode, - NAcdEvent * event) + const NMEtherAddr *sender_addr, + gint64 * p_now_msec) + { - guint32 acd_timeout_msec; - gint64 now_msec = 0; - const char *log_reason; - gboolean was_probing; + guint32 acd_timeout_msec; + NML3AcdDefendType acd_defend_type; + gint64 now_msec; + const char * log_reason; + char sbuf256[256]; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + if (!p_now_msec) { + now_msec = 0; + p_now_msec = &now_msec; + } /* Keeping track of ACD inevitably requires keeping (and mutating) state. Then a multitude of * things can happen, and depending on the state, we need to do something. * * Here, all the state for one address that we probe/announce is tracked in AcdData/acd_data. * - * The acd_data has a list of AcdTrackData/acd_track_lst_head, which are configuration items + * The acd_data has a list of NML3AcdAddrTrackInfo/acd_track_lst_head, which are configuration items * that are interested in configuring this address. The "owners" of the ACD check for a certain * address. * @@ -1644,415 +1812,533 @@ _l3_acd_data_state_change(NML3Cfg * self, nm_assert(NM_IS_L3CFG(self)); nm_assert(acd_data); - nm_assert(!c_list_is_empty(&acd_data->acd_track_lst_head)); - - was_probing = acd_data->acd_state < ACD_STATE_PROBE_DONE; + nm_assert(acd_data->info.n_track_infos); + nm_assert(NM_IN_SET(acd_data->info.state, + NM_L3_ACD_ADDR_STATE_CONFLICT, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING, + NM_L3_ACD_ADDR_STATE_INIT, + NM_L3_ACD_ADDR_STATE_PROBING, + NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED, + NM_L3_ACD_ADDR_STATE_USED)); + nm_assert(!acd_data->track_infos_changed + || NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_INIT, + ACD_STATE_CHANGE_MODE_INIT_REAPPLY, + ACD_STATE_CHANGE_MODE_POST_COMMIT, + ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED, + ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED)); + nm_assert((!!sender_addr) + == NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_NACD_USED, + ACD_STATE_CHANGE_MODE_NACD_CONFLICT, + ACD_STATE_CHANGE_MODE_NACD_DEFENDED)); + + if (acd_data->info.state == NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED) { + /* once remove, the state can only change by external added or during + * the POST-COMMIT check. */ + if (!NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_POST_COMMIT, + ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED)) + return; + } switch (state_change_mode) { case ACD_STATE_CHANGE_MODE_INIT: - { - AcdTrackData *acd_track; - gboolean any_no_timeout; - - /* we are called from _l3_acd_data_add_all(), and we do a fast check whether - * newly tracked entries already passed ACD so that we can use the address - * right away. */ - - if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->addr)) { - /* the address is already configured on the link. It is an automatic pass. */ - if (_acd_data_collect_tracks_data(acd_data, FALSE, NM_TERNARY_DEFAULT, NULL) <= 0) { - /* The entry has no non-dirty trackers, that means, it's no longer referenced - * and will be removed during the next _l3_acd_data_prune(). We can ignore - * this entry. */ + case ACD_STATE_CHANGE_MODE_INIT_REAPPLY: + + /* We are called right before commit. We check whether we have a acd_data + * in INIT or PROBING state. In that case, maybe the new configuration + * disables ACD, or we have the address already configured (which also let's + * us skip/cancel the probing). The point is that if the address would be ready + * already, we want to commit it right away. */ + + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_PROBING: + case NM_L3_ACD_ADDR_STATE_INIT: + case NM_L3_ACD_ADDR_STATE_USED: + goto handle_init; + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + if (state_change_mode != ACD_STATE_CHANGE_MODE_INIT_REAPPLY) return; + goto handle_init; + } + nm_assert_not_reached(); + return; + +handle_init: + if (_acd_data_collect_tracks_data(acd_data, + NM_TERNARY_FALSE, + &acd_timeout_msec, + &acd_defend_type) + <= 0u) { + /* the acd_data has no active trackers. It will soon be pruned. */ + return; + } + + if (acd_timeout_msec == 0u) + log_reason = "acd disabled by configuration"; + else if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->info.addr)) + log_reason = "address already configured"; + else { + if (state_change_mode == ACD_STATE_CHANGE_MODE_INIT_REAPPLY) { + /* during a reapply, we forget all the state and start from scratch. */ + _LOGT_acd(acd_data, "reset state for reapply"); + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + _l3_acd_data_state_set(self, acd_data, NM_L3_ACD_ADDR_STATE_INIT, FALSE); } - log_reason = "address initially already configured"; - goto handle_probing_acd_good; + return; } - /* we are called at the end of _l3_acd_data_add_all(). We updated the list of a - * all tracked IP addresses before we actually collect the addresses that are - * ready. We don't do regular handling of ACD states at this point, however, - * we check whether ACD for new elements is disabled entirely, so we can signal - * the address are ready right away (without going through another hop). */ + _LOGT_acd(acd_data, + "%s probing (%s, during pre-check)", + acd_data->info.state == NM_L3_ACD_ADDR_STATE_INIT ? "skip" : "cancel", + log_reason); + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + acd_data->acd_defend_type_desired = acd_defend_type; + _l3_acd_data_state_set(self, acd_data, NM_L3_ACD_ADDR_STATE_READY, FALSE); + return; - if (acd_data->acd_state != ACD_STATE_INIT) { - /* this element is not new and we don't perform the quick-check. */ + case ACD_STATE_CHANGE_MODE_POST_COMMIT: + + if (acd_data->track_infos_changed) { + acd_data->track_infos_changed = FALSE; + _nm_l3cfg_emit_signal_notify_acd_event_queue(self, acd_data); + } + + if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->info.addr)) { + log_reason = "address already configured"; + goto handle_probing_done; + } + + if (acd_data->info.state == NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED) return; + + /* we just did a commit of the IP configuration and now visit all ACD states + * and kick off the necessary actions... */ + if (_acd_data_collect_tracks_data(acd_data, + NM_TERNARY_TRUE, + &acd_timeout_msec, + &acd_defend_type) + <= 0) + nm_assert_not_reached(); + + acd_data->acd_defend_type_desired = acd_defend_type; + + if (acd_timeout_msec <= 0) { + log_reason = "acd disabled by configuration"; + goto handle_probing_done; } - any_no_timeout = FALSE; - c_list_for_each_entry (acd_track, &acd_data->acd_track_lst_head, acd_track_lst) { - /* There should be no dirty trackers, because the element is in init-state. */ - nm_assert(!acd_track->acd_dirty); - if (acd_track->acd_timeout_msec <= 0) { - /* ACD for this element is disabled. We can process is right away. */ - any_no_timeout = TRUE; - break; + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + nm_assert(!acd_data->nacd_probe); + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); + acd_data->probing_timestamp_msec = (*p_now_msec); + acd_data->probing_timeout_msec = acd_timeout_msec; + _nm_l3cfg_emit_signal_notify_acd_event_queue(self, acd_data); + log_reason = "initial post-commit"; + goto handle_start_probing; + + case NM_L3_ACD_ADDR_STATE_PROBING: + { + gint64 old_expiry_msec; + gint64 new_expiry_msec; + + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); + + new_expiry_msec = (*p_now_msec) + acd_timeout_msec; + old_expiry_msec = acd_data->probing_timestamp_msec + acd_data->probing_timeout_msec; + + if (!acd_data->nacd_probe) { + /* we are currently waiting for restarting a probe. At this point, at most we have + * to adjust the timeout/timestamp and let the regular timeouts handle this. */ + + if (new_expiry_msec >= old_expiry_msec) { + /* the running timeout expires before the new timeout. We don't update the timestamp/timeout, + * because we don't want to prolong the overall probing time. */ + return; + } + /* update the timers after out timeout got reduced. Also, reschedule the timeout + * so that it expires immediately. */ + acd_data->probing_timestamp_msec = (*p_now_msec); + acd_data->probing_timeout_msec = acd_timeout_msec; + _l3_acd_data_timeout_schedule(acd_data, 0); + return; + } + + if (new_expiry_msec >= old_expiry_msec) { + /* we already have ACD running with a timeout that expires before the requested one. There + * is nothing to do at this time. */ + return; } + + /* the timeout got reduced. We try to restart the probe. */ + acd_data->probing_timestamp_msec = (*p_now_msec); + acd_data->probing_timeout_msec = acd_timeout_msec; + log_reason = "post-commit timeout update"; + goto handle_start_probing; } - if (!any_no_timeout) { - /* there are elements that request the address, but they all specify - * an ACD timeout. We cannot progress the state. */ + + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + /* we are done for now. We however scheduled a timeout to restart. This + * will be handled with the ACD_STATE_CHANGE_MODE_TIMEOUT event. */ return; - } - /* ACD is disabled, we can artificially moving the state further to - * ACD_STATE_PROBE_DONE and configure the address right away. This avoids - * that we go through another hop. - */ - log_reason = "ACD disabled by configuration from the start"; - goto handle_probing_acd_good; - } + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + goto handle_start_defending; - case ACD_STATE_CHANGE_MODE_POST_COMMIT: - acd_data->initializing = FALSE; - goto handle_post_commit; + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + nm_assert_not_reached(); + return; + } + nm_assert_not_reached(); + return; case ACD_STATE_CHANGE_MODE_TIMEOUT: - { - if (acd_data->acd_state == ACD_STATE_PROBING && !acd_data->nacd_probe) { - const char *failure_reason; - gboolean acd_not_supported; - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + nm_assert_not_reached(); + return; + + case NM_L3_ACD_ADDR_STATE_PROBING: + if (acd_data->nacd_probe) { + /* we are already probing. There is nothing to do for this timeout. */ + return; + } + + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); if (acd_data->probing_timestamp_msec + ACD_WAIT_PROBING_EXTRA_TIME_MSEC + ACD_WAIT_PROBING_EXTRA_TIME2_MSEC - >= now_msec) { + >= (*p_now_msec)) { + /* hm. We failed to create a new probe too long. Something is really wrong + * internally, but let's ignore the issue and assume the address is good. What + * else would we do? Assume the address is USED? */ _LOGT_acd(acd_data, - "state: probe-good (waiting for creating probe timed out. Assume good)"); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; + "probe-good (waiting for creating probe timed out. Assume good)"); + goto handle_start_defending; } - /* try create a new probe. The timeout is always as originally requested. */ - acd_data->nacd_probe = - _l3_acd_nacd_instance_create_probe(self, - acd_data->addr, - acd_data->probing_timeout_msec, - acd_data, - &acd_not_supported, - &failure_reason); - if (acd_not_supported) { - nm_assert(!acd_data->nacd_probe); - _LOGT_acd( - acd_data, - "state: probe-good (interface does not support ACD anymore after timeout)"); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; + log_reason = "retry probing on timeout"; + goto handle_start_probing; + + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + + nm_assert(!acd_data->nacd_probe); + + /* after a timeout, re-probe the address. This only happens if the caller + * does not deconfigure the address after USED/CONFLICT. But in that case, + * we eventually want to retry. */ + if (_acd_data_collect_tracks_data(acd_data, + NM_TERNARY_TRUE, + &acd_timeout_msec, + &acd_defend_type) + <= 0) + nm_assert_not_reached(); + + acd_data->acd_defend_type_desired = acd_defend_type; + + if (acd_timeout_msec <= 0) { + log_reason = "acd disabled by configuration (restart after previous conflict)"; + goto handle_probing_done; } - if (!acd_data->nacd_probe) { - _LOGT_acd(acd_data, - "state: probing not possible at this time (%s). Wait longer", - failure_reason); - _l3_acd_data_timeout_schedule_probing_restart(acd_data, now_msec); - return; + if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->info.addr)) { + log_reason = "address already configured (restart after previous conflict)"; + goto handle_probing_done; } - /* probing started (with the original timeout. Note that acd_data->probing_time*_msec - * no longer corresponds to the actual timeout of the nacd_probe. This is not a problem - * because at this point we only trust the internal timer from nacd_probe to get - * it right. Instead, we keep acd_data->probing_time*_msec unchanged, to remember when - * we originally wanted to start. */ - _LOGT_acd(acd_data, - "state: probing started (after retry, timeout %u msec)", - acd_data->probing_timeout_msec); + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); + acd_data->probing_timestamp_msec = (*p_now_msec); + acd_data->probing_timeout_msec = acd_timeout_msec; + if (acd_data->info.state == NM_L3_ACD_ADDR_STATE_USED) + log_reason = "restart probing after previously used address"; + else + log_reason = "restart probing after previous conflict"; + goto handle_start_probing; + + case NM_L3_ACD_ADDR_STATE_READY: + nm_assert_not_reached(); return; - } - if (acd_data->acd_state == ACD_STATE_PROBE_DONE && !acd_data->probe_result) { - /* Probing is done, but previously we detected a conflict. After a restart, we retry to - * probe. */ + case NM_L3_ACD_ADDR_STATE_DEFENDING: + nm_assert(!acd_data->nacd_probe); - nm_assert(!acd_data->announcing_failed_is_retrying); + _LOGT_acd(acd_data, "retry announcing address"); + goto handle_start_defending; - _LOGT_acd(acd_data, "state: restart a new probe after previous conflict"); - acd_data->acd_state = ACD_STATE_INIT; - goto handle_post_commit; + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + nm_assert_not_reached(); + return; } - if (acd_data->acd_state == ACD_STATE_PROBE_DONE && acd_data->probe_result - && !acd_data->nacd_probe && acd_data->announcing_failed_is_retrying) { - /* Probing is done, but previously we failed to start announcing. Retry now. */ - nm_assert(!was_probing); - _LOGT_acd(acd_data, "state: retry announcing address"); - acd_data->announcing_failed_is_retrying = FALSE; - goto handle_probe_done; + nm_assert_not_reached(); + return; + + case ACD_STATE_CHANGE_MODE_NACD_USED: + nm_assert(acd_data->info.state == NM_L3_ACD_ADDR_STATE_PROBING); + nm_assert(acd_data->nacd_probe); + + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + acd_data->last_conflict_addr = *sender_addr; + _l3_acd_data_state_set_full(self, + acd_data, + NM_L3_ACD_ADDR_STATE_USED, + TRUE, + "acd completed with address already in use by %s", + nm_ether_addr_to_string_a(sender_addr)); + + if (!acd_data->acd_data_timeout_source) + _l3_acd_data_timeout_schedule(acd_data, ACD_WAIT_TIME_PROBING_FULL_RESTART_MSEC); + + if (!_l3_acd_data_defendconflict_warning_ratelimited(acd_data, p_now_msec)) { + _LOGI("IPv4 address %s is used on network connected to interface %d%s%s%s from " + "host %s", + _nm_utils_inet4_ntop(acd_data->info.addr, sbuf_addr), + self->priv.ifindex, + NM_PRINT_FMT_QUOTED(self->priv.plobj_next, + " (", + NMP_OBJECT_CAST_LINK(self->priv.plobj_next)->name, + ")", + ""), + nm_ether_addr_to_string_a(sender_addr)); } + return; + case ACD_STATE_CHANGE_MODE_NACD_DEFENDED: + nm_assert(acd_data->info.state == NM_L3_ACD_ADDR_STATE_DEFENDING); + _LOGT_acd(acd_data, + "address %s defended from %s", + _nm_utils_inet4_ntop(acd_data->info.addr, sbuf_addr), + nm_ether_addr_to_string_a(sender_addr)); + /* we just log an info message. Nothing else to do. */ return; - } - case ACD_STATE_CHANGE_MODE_NACD_READY: - if (acd_data->acd_state == ACD_STATE_PROBING) { - log_reason = "acd indicates ready"; - goto handle_probing_acd_good; + case ACD_STATE_CHANGE_MODE_NACD_CONFLICT: + nm_assert(acd_data->info.state == NM_L3_ACD_ADDR_STATE_DEFENDING); + + _LOGT_acd(acd_data, + "address conflict for %s detected with %s", + _nm_utils_inet4_ntop(acd_data->info.addr, sbuf_addr), + nm_ether_addr_to_string_a(sender_addr)); + + if (!_l3_acd_data_defendconflict_warning_ratelimited(acd_data, p_now_msec)) { + _LOGW("IPv4 address collision detection sees conflict on interface %d%s%s%s for " + "address %s from host %s", + self->priv.ifindex, + NM_PRINT_FMT_QUOTED(self->priv.plobj_next, + " (", + NMP_OBJECT_CAST_LINK(self->priv.plobj_next)->name, + ")", + ""), + _nm_utils_inet4_ntop(acd_data->info.addr, sbuf_addr), + nm_ether_addr_to_string_a(sender_addr)); } - if (acd_data->acd_state == ACD_STATE_ANNOUNCING) { - _LOGT_acd(acd_data, "state: ready to start announcing"); - if (n_acd_probe_announce(acd_data->nacd_probe, N_ACD_DEFEND_ALWAYS) != 0) + + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + acd_data->last_conflict_addr = *sender_addr; + _l3_acd_data_state_set(self, acd_data, NM_L3_ACD_ADDR_STATE_CONFLICT, TRUE); + if (!acd_data->acd_data_timeout_source) + _l3_acd_data_timeout_schedule(acd_data, ACD_WAIT_TIME_CONFLICT_RESTART_MSEC); + return; + + case ACD_STATE_CHANGE_MODE_NACD_READY: + + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_PROBING: + nm_assert(acd_data->nacd_probe); + /* we theoretically could re-use this probe for defending. But as we + * may not start defending right away, it makes it more complicated. */ + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + log_reason = "acd indicates ready"; + goto handle_probing_done; + case NM_L3_ACD_ADDR_STATE_DEFENDING: + nm_assert(!acd_data->acd_defend_type_is_active); + acd_data->acd_defend_type_is_active = TRUE; + _LOGT_acd(acd_data, + "start announcing (defend=%s) (after new probe ready)", + _l3_acd_defend_type_to_string(acd_data->acd_defend_type_current, + sbuf256, + sizeof(sbuf256))); + if (n_acd_probe_announce(acd_data->nacd_probe, + _l3_acd_defend_type_to_nacd(acd_data->acd_defend_type_current)) + != 0) nm_assert_not_reached(); return; + case NM_L3_ACD_ADDR_STATE_INIT: + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + nm_assert_not_reached(); + return; } - /* nacd really shouldn't call us in this state. There is a bug somewhere. */ nm_assert_not_reached(); return; - case ACD_STATE_CHANGE_MODE_NACD_USED: - { - gs_free char *str_to_free = NULL; + case ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED: - nm_assert(acd_data->acd_state == ACD_STATE_PROBING); - _LOGT_acd(acd_data, - "state: probe-done bad (address already in use by %s)", - nm_utils_bin2hexstr_a(event->_acd_event_payload.sender, - event->_acd_event_payload.n_sender, - ':', - FALSE, - &str_to_free)); - acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = FALSE; - goto handle_probe_done; - } + if (self->priv.p->commit_reentrant_count > 0) + return; - case ACD_STATE_CHANGE_MODE_EXTERNAL_ADDED: - /* the address is configured on the link. This means, ACD passed */ - log_reason = "address configured on link"; - goto handle_probing_acd_good; + _LOGT_acd(acd_data, "address was externally added"); - case ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED: - /* The address got removed. Either we ourself removed it or it was removed externally. - * In either case, it's not clear what we should do about that, regardless in which - * ACD state we are, so ignore it. */ - _LOGT_acd(acd_data, "state: address was externally removed. Ignore"); - return; + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + nm_assert_not_reached(); + return; + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + goto handle_start_defending; + case NM_L3_ACD_ADDR_STATE_PROBING: + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + log_reason = "address configured on link"; + goto handle_probing_done; + } - case ACD_STATE_CHANGE_MODE_NACD_DOWN: - if (acd_data->acd_state < ACD_STATE_PROBE_DONE) { - /* we are probing, but the probe has a problem that the link went down. Maybe - * we need to restart. */ + nm_assert_not_reached(); + return; - nm_assert(acd_data->acd_state == ACD_STATE_PROBING); + case ACD_STATE_CHANGE_MODE_EXTERNAL_REMOVED: - if (!acd_data->nacd_probe) { - /* we are in probing state, but currently not really probing. A timer is - * running, and we will handle this situation that way. */ - return; - } + if (self->priv.p->commit_reentrant_count > 0) + return; - /* We abort the probing, but we also schedule a timer to restart it. Let - * the regular re-start handling handle this. */ - _LOGT_acd(acd_data, - "state: interface-down. Probing aborted but we keep waiting to retry"); - acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); - _l3_acd_data_timeout_schedule_probing_restart(acd_data, now_msec); + if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->info.addr)) { + /* this can happen, because there might still be the same address with different + * plen or peer_address. */ return; } - /* We already completed a probe and acted accordingly (by either configuring the address - * already or by rejecting it). We cannot (easily) re-evaluate what to do now. Should - * we later restart probing? But what about the decisions we already made?? - * Ignore the situation. */ + _LOGT_acd(acd_data, "address was externally removed"); + + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + _l3_acd_data_state_set(self, acd_data, NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED, FALSE); return; + case ACD_STATE_CHANGE_MODE_NACD_DOWN: case ACD_STATE_CHANGE_MODE_LINK_NOW_UP: - /* The interface just came up. */ - - if (acd_data->acd_state <= ACD_STATE_PROBING) { - nm_auto(n_acd_probe_freep) NAcdProbe *probe = NULL; - const char * failure_reason; - gboolean acd_not_supported; - - /* the interface was probing. We will restart the probe. */ - nm_assert(acd_data->acd_state == ACD_STATE_PROBING); - - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + nm_assert_not_reached(); + return; + case NM_L3_ACD_ADDR_STATE_PROBING: if (!acd_data->nacd_probe) { - /* We currently are waiting to restart probing. We don't handle the link-up - * event here, we only trigger a timeout right away. */ + /* we failed starting to probe before and have a timer running to + * restart. We don't do anything now, but let the timer handle it. + * This also implements some rate limiting for us. */ _LOGT_acd(acd_data, - "state: ignore link up event while we are waiting to start probing"); - _l3_acd_data_timeout_schedule(acd_data, now_msec, now_msec, TRUE); + "ignore link %s event while we are waiting to start probing", + state_change_mode == ACD_STATE_CHANGE_MODE_NACD_DOWN ? "down" : "up"); return; } - if (acd_data->probing_timestamp_msec + ACD_WAIT_PROBING_RESTART_TIME_MSEC >= now_msec) { - /* This probe was already started quite a while ago. We ignore the link-up event - * and let it complete regularly. This is to avoid restarting to probing indefinitely. */ - _LOGT_acd(acd_data, "state: ignore link up event for a probe started long ago"); - return; - } + nm_utils_get_monotonic_timestamp_msec_cached(p_now_msec); - probe = _l3_acd_nacd_instance_create_probe(self, - acd_data->addr, - acd_data->probing_timeout_msec, - acd_data, - &acd_not_supported, - &failure_reason); - if (!probe) { - _LOGT_acd(acd_data, - "state: link up event would cause to retry probing, but creating a probe " - "failed (%s). Ignore and keep previous probe", - failure_reason); + if (acd_data->probing_timestamp_msec + acd_data->probing_timeout_msec + + ACD_WAIT_PROBING_EXTRA_TIME_MSEC + ACD_WAIT_PROBING_EXTRA_TIME2_MSEC + >= (*p_now_msec)) { + /* The probing already started quite a while ago. We ignore the link event + * and let the probe come to it's natural end. */ + _LOGT_acd(acd_data, "ignore link up event for a probe started long ago"); return; } - NM_SWAP(&probe, &acd_data->nacd_probe); - - /* We just restarted probing. Note that we don't touch the original acd_data->probing_time*_msec - * times, otherwise a repeated link up/down cycle could extend the probing indefinitely. - * - * This is despite the new probe just started counting now. So, at this point, the - * timestamp/timeout of acd_data no longer corresponds to the internal timestamp of - * acd_data->nacd_probe. But since we don't run our own timer against the internal timer of - * acd_data->nacd_probe, that is not a problem. - */ - _LOGT_acd(acd_data, - "state: probing restarted (after link up, new timeout %u msec)", - acd_data->probing_timeout_msec); + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + if (state_change_mode == ACD_STATE_CHANGE_MODE_NACD_DOWN) + log_reason = "restart probing after down event"; + else + log_reason = "restart probing after link up"; + goto handle_start_probing; + + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + /* if the link was down/came up, it's no clear what we should do about these + * cases. Ignore the event. */ return; } - - /* we are already done with the ACD state. Bringing up an interface has - * no further consequence w.r.t. the ACD state. */ + nm_assert_not_reached(); return; case ACD_STATE_CHANGE_MODE_INSTANCE_RESET: - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - if (acd_data->acd_state <= ACD_STATE_PROBING) { - nm_assert(acd_data->acd_state == ACD_STATE_PROBING); - - _LOGT_acd( - acd_data, - "state: n-acd instance reset. Trigger a restart of the probing (was %sprobing)", - acd_data->nacd_probe ? "" : "not"); - /* Just destroy the current probe (if any) and retrigger a restart right away. */ - acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); - _l3_acd_data_timeout_schedule(acd_data, now_msec, now_msec, TRUE); + + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + nm_assert_not_reached(); return; - } + case NM_L3_ACD_ADDR_STATE_PROBING: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + + if (!acd_data->nacd_probe) { + /* we failed starting to probe before and have a timer running to + * restart. We don't do anything now, but let the timer handle it. + * This also implements some rate limiting for us. */ + _LOGT_acd(acd_data, + "n-acd instance reset. Ignore event while restarting %s", + (acd_data->info.state == NM_L3_ACD_ADDR_STATE_PROBING) ? "probing" + : "defending"); + return; + } - if (acd_data->probe_result) { - _LOGT_acd(acd_data, "state: n-acd instance reset. Restart announcing"); - } else { _LOGT_acd(acd_data, - "state: n-acd instance reset. Reprobe the address that conflicted before"); + "n-acd instance reset. Trigger a restart of the %s", + (acd_data->info.state == NM_L3_ACD_ADDR_STATE_PROBING) ? "probing" + : "defending"); + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); + _l3_acd_data_timeout_schedule(acd_data, 0); + return; + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_USED: + case NM_L3_ACD_ADDR_STATE_CONFLICT: + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + nm_assert(!acd_data->nacd_probe); + return; } - acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - _l3_acd_data_timeout_schedule(acd_data, now_msec, now_msec, TRUE); + nm_assert_not_reached(); return; } nm_assert_not_reached(); return; -handle_post_commit: - /* we just did a commit of the IP configuration and now visit all ACD states - * and kick off the necessary actions... */ - if (_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->addr)) { - log_reason = "address already configured"; - goto handle_probing_acd_good; - } - if (_acd_data_collect_tracks_data(acd_data, TRUE, NM_TERNARY_DEFAULT, &acd_timeout_msec) <= 0) - nm_assert_not_reached(); - if (acd_timeout_msec <= 0) { - log_reason = "ACD disabled by configuration"; - goto handle_probing_acd_good; - } - - switch (acd_data->acd_state) { - case ACD_STATE_INIT: - { - const char *failure_reason; - gboolean acd_not_supported; - NAcdProbe * probe; - - nm_assert(!acd_data->nacd_probe); - - probe = _l3_acd_nacd_instance_create_probe(self, - acd_data->addr, - acd_timeout_msec, - acd_data, - &acd_not_supported, - &failure_reason); - if (acd_not_supported) { - nm_assert(!probe); - _LOGT_acd(acd_data, "state: probe-good (interface does not support ACD)"); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; - } - - if (!probe) { - _LOGT_acd(acd_data, - "state: probing currently not possible (timeout %u msec; %s)", - acd_timeout_msec, - failure_reason); - acd_data->acd_state = ACD_STATE_PROBING; - acd_data->probing_timeout_msec = acd_timeout_msec; - acd_data->probing_timestamp_msec = - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - _l3_acd_data_timeout_schedule_probing_restart(acd_data, now_msec); - return; - } - - _LOGT_acd(acd_data, "state: start probing (timeout %u msec)", acd_timeout_msec); - acd_data->acd_state = ACD_STATE_PROBING; - acd_data->nacd_probe = probe; - acd_data->probing_timeout_msec = acd_timeout_msec; - acd_data->probing_timestamp_msec = nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - return; - } - - case ACD_STATE_PROBING: - { - nm_auto(n_acd_probe_freep) NAcdProbe *probe = NULL; +handle_start_probing: + if (TRUE) { + const NML3AcdAddrState orig_state = acd_data->info.state; + nm_auto(n_acd_probe_freep) NAcdProbe *probe = NULL; const char * failure_reason; gboolean acd_not_supported; - gint64 old_expiry_msec; - gint64 new_expiry_msec; - - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - - new_expiry_msec = now_msec + acd_timeout_msec; - old_expiry_msec = acd_data->probing_timestamp_msec + acd_data->probing_timeout_msec; - if (!acd_data->nacd_probe) { - /* we are currently waiting for restarting a probe. At this point, at most we have - * to adjust the timeout/timestamp and let the regular timeouts handle this. */ - - if (new_expiry_msec >= old_expiry_msec) { - /* the running timeout expires before the new timeout. We don't update the timestamp/timerout, - * because we don't want to prolong the overall probing time. */ - return; - } - /* update the timers after out timeout got reduced. Also, reschedule the timeout - * so that it expires immediately. */ - acd_data->probing_timestamp_msec = now_msec; - acd_data->probing_timeout_msec = acd_timeout_msec; - _l3_acd_data_timeout_schedule(acd_data, now_msec, now_msec, TRUE); - return; - } + nm_assert(NM_IN_SET(acd_data->info.state, + NM_L3_ACD_ADDR_STATE_INIT, + NM_L3_ACD_ADDR_STATE_PROBING, + NM_L3_ACD_ADDR_STATE_USED, + NM_L3_ACD_ADDR_STATE_CONFLICT)); - if (new_expiry_msec >= old_expiry_msec) { - /* we already have ACD running with a timeout that expires before the requested one. There - * is nothing to do at this time. */ - return; - } + /* note that we reach this line also during a ACD_STATE_CHANGE_MODE_TIMEOUT, when + * or when we restart the probing (with a new timeout). In all cases, we still + * give the original timeout (acd_data->probing_timeout_msec), and not the remaining + * time. That means, the probing step might take longer then originally planned + * (e.g. if we initially cannot start probing right away). */ - /* the timeout got reduced. We try to restart the probe. */ probe = _l3_acd_nacd_instance_create_probe(self, - acd_data->addr, - acd_timeout_msec, + acd_data->info.addr, + acd_data->probing_timeout_msec, acd_data, &acd_not_supported, &failure_reason); @@ -2060,143 +2346,144 @@ handle_post_commit: if (acd_not_supported) { nm_assert(!acd_data->nacd_probe); - _LOGT_acd(acd_data, "state: probe-good (interface does not support ACD anymore)"); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; + _LOGT_acd(acd_data, + "probe-good (interface does not support acd%s, %s)", + orig_state == NM_L3_ACD_ADDR_STATE_INIT ? "" + : (state_change_mode != ACD_STATE_CHANGE_MODE_TIMEOUT) + ? " anymore" + : " anymore after timeout", + log_reason); + goto handle_start_defending; } + _l3_acd_data_state_set(self, + acd_data, + NM_L3_ACD_ADDR_STATE_PROBING, + !NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_INIT, + ACD_STATE_CHANGE_MODE_INIT_REAPPLY, + ACD_STATE_CHANGE_MODE_POST_COMMIT)); + if (!acd_data->nacd_probe) { _LOGT_acd(acd_data, - "state: probing currently still not possible (timeout %u msec; %s)", - acd_timeout_msec, - failure_reason); - acd_data->acd_state = ACD_STATE_PROBING; - acd_data->probing_timeout_msec = acd_timeout_msec; - acd_data->probing_timestamp_msec = now_msec; - _l3_acd_data_timeout_schedule_probing_restart(acd_data, now_msec); + "probing currently %snot possible (timeout %u msec; %s, %s)", + orig_state == NM_L3_ACD_ADDR_STATE_INIT ? "" : " still", + acd_data->probing_timeout_msec, + failure_reason, + log_reason); + _l3_acd_data_timeout_schedule_probing_restart(acd_data, (*p_now_msec)); return; } - /* We update the timestamps (after also restarting the probe). - * - * Note that we only reduced the overall expiry. */ - acd_data->probing_timestamp_msec = now_msec; - acd_data->probing_timeout_msec = acd_timeout_msec; - _LOGT_acd(acd_data, "state: restart probing (timeout %u msec)", acd_timeout_msec); + _LOGT_acd(acd_data, + "%sstart probing (timeout %u msec, %s)", + orig_state == NM_L3_ACD_ADDR_STATE_INIT ? "" : "re", + acd_data->probing_timeout_msec, + log_reason); return; } - case ACD_STATE_PROBE_DONE: - case ACD_STATE_ANNOUNCING: - goto handle_probe_done; - } - nm_assert_not_reached(); - return; - -handle_probing_acd_good: - switch (acd_data->acd_state) { - case ACD_STATE_INIT: - _LOGT_acd(acd_data, "state: probe-done good (%s, initializing)", log_reason); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; - case ACD_STATE_PROBING: - _LOGT_acd(acd_data, "state: probe-done good (%s, probing done)", log_reason); +handle_probing_done: + switch (acd_data->info.state) { + case NM_L3_ACD_ADDR_STATE_INIT: + _LOGT_acd(acd_data, "probe-done good (%s, initializing)", log_reason); + goto handle_start_defending; + case NM_L3_ACD_ADDR_STATE_PROBING: + _LOGT_acd(acd_data, "probe-done good (%s, probing done)", log_reason); if (state_change_mode != ACD_STATE_CHANGE_MODE_NACD_READY) acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); - acd_data->acd_state = ACD_STATE_PROBE_DONE; - acd_data->probe_result = TRUE; - goto handle_probe_done; - case ACD_STATE_PROBE_DONE: - if (!acd_data->probe_result) { - nm_assert(!acd_data->nacd_probe); - _LOGT_acd(acd_data, "state: probe-done good (%s, after probe failed)", log_reason); - acd_data->probe_result = TRUE; - } - goto handle_probe_done; - case ACD_STATE_ANNOUNCING: - nm_assert(acd_data->probe_result); - goto handle_probe_done; - } - nm_assert_not_reached(); - return; - -handle_probe_done: - nm_assert(NM_IN_SET(acd_data->acd_state, ACD_STATE_PROBE_DONE, ACD_STATE_ANNOUNCING)); - - if (acd_data->initializing) + goto handle_start_defending; + case NM_L3_ACD_ADDR_STATE_USED: + _LOGT_acd(acd_data, "probe-done good (%s, after probe failed)", log_reason); + goto handle_start_defending; + case NM_L3_ACD_ADDR_STATE_READY: + case NM_L3_ACD_ADDR_STATE_DEFENDING: + goto handle_start_defending; + case NM_L3_ACD_ADDR_STATE_CONFLICT: return; - - if (acd_data->acd_state >= ACD_STATE_ANNOUNCING) { - nm_assert(acd_data->nacd_probe); - nm_assert(acd_data->probe_result); + case NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED: + nm_assert_not_reached(); return; } + nm_assert_not_reached(); + return; - if (!acd_data->probe_result) { - nm_assert(acd_data->acd_state == ACD_STATE_PROBE_DONE); - nm_assert(!acd_data->nacd_probe); - /* we just completed probing with negative result. - * Emit a signal, but also reschedule a timer to restart. */ - if (was_probing) { - _LOGT_acd(acd_data, "state: acd probe failed; signal failure"); - acd_data->probing_timestamp_msec = - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - _l3_acd_data_timeout_schedule_probing_full_restart(acd_data, now_msec); +handle_start_defending: + if (!_l3_acd_ipv4_addresses_on_link_contains(self, acd_data->info.addr)) { + if (acd_data->info.state != NM_L3_ACD_ADDR_STATE_READY) { + _l3_acd_data_state_set_full(self, + acd_data, + NM_L3_ACD_ADDR_STATE_READY, + !NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_INIT, + ACD_STATE_CHANGE_MODE_INIT_REAPPLY, + ACD_STATE_CHANGE_MODE_POST_COMMIT), + "probe is ready, waiting for address to be configured"); } - _l3_acd_data_notify_acd_completed_queue(self, acd_data); return; } - if (was_probing && acd_data->probe_result) { - /* probing just completed. Schedule handling the change. */ - _LOGT_acd(acd_data, "state: acd probe succeed"); - _l3_acd_data_notify_acd_completed_queue(self, acd_data); - if (state_change_mode != ACD_STATE_CHANGE_MODE_POST_COMMIT) - _l3_changed_configs_set_dirty(self); - nm_l3cfg_commit_on_idle_schedule(self); + _l3_acd_data_state_set(self, + acd_data, + NM_L3_ACD_ADDR_STATE_DEFENDING, + !NM_IN_SET(state_change_mode, + ACD_STATE_CHANGE_MODE_INIT, + ACD_STATE_CHANGE_MODE_INIT_REAPPLY, + ACD_STATE_CHANGE_MODE_POST_COMMIT)); + + nm_assert(acd_data->acd_defend_type_desired > NM_L3_ACD_DEFEND_TYPE_NONE); + nm_assert(acd_data->acd_defend_type_desired <= NM_L3_ACD_DEFEND_TYPE_ALWAYS); + + if (acd_data->acd_defend_type_desired != acd_data->acd_defend_type_current) { + acd_data->acd_defend_type_current = acd_data->acd_defend_type_desired; + acd_data->nacd_probe = n_acd_probe_free(acd_data->nacd_probe); } if (!acd_data->nacd_probe) { const char *failure_reason; NAcdProbe * probe; - if (acd_data->announcing_failed_is_retrying) { + if (acd_data->acd_data_timeout_source) { /* we already failed to create a probe. We are ratelimited to retry, but * we have a timer pending... */ return; } probe = _l3_acd_nacd_instance_create_probe(self, - acd_data->addr, + acd_data->info.addr, 0, acd_data, NULL, &failure_reason); if (!probe) { - /* we failed to create a probe for announcing the address. We log a (rate limited) - * warning and start a timer to retry. */ - _LOGT_acd(acd_data, - "state: start announcing failed to create probe (%s)", - failure_reason); - acd_data->announcing_failed_is_retrying = TRUE; - acd_data->probing_timestamp_msec = - nm_utils_get_monotonic_timestamp_msec_cached(&now_msec); - _l3_acd_data_timeout_schedule_announce_restart(acd_data, now_msec); + /* we failed to create a probe for announcing the address. We log a + * warning and start a timer to retry. This way (of having a timer pending) + * we also back off and are rate limited from retrying too frequently. */ + _LOGT_acd(acd_data, "start announcing failed to create probe (%s)", failure_reason); + _l3_acd_data_timeout_schedule(acd_data, ACD_WAIT_TIME_ANNOUNCE_RESTART_MSEC); return; } - _LOGT_acd(acd_data, "state: start announcing (with new probe)"); - acd_data->nacd_probe = probe; - acd_data->acd_state = ACD_STATE_ANNOUNCING; + _LOGT_acd(acd_data, + "start announcing (defend=%s) (probe created)", + _l3_acd_defend_type_to_string(acd_data->acd_defend_type_current, + sbuf256, + sizeof(sbuf256))); + acd_data->acd_defend_type_is_active = FALSE; + acd_data->nacd_probe = probe; return; } - if (acd_data->acd_state == ACD_STATE_PROBE_DONE) { - _LOGT_acd(acd_data, "state: start announcing (with existing probe)"); - acd_data->acd_state = ACD_STATE_ANNOUNCING; - if (n_acd_probe_announce(acd_data->nacd_probe, N_ACD_DEFEND_ALWAYS) != 0) + if (!acd_data->acd_defend_type_is_active) { + acd_data->acd_defend_type_is_active = TRUE; + _LOGT_acd(acd_data, + "start announcing (defend=%s) (with existing probe)", + _l3_acd_defend_type_to_string(acd_data->acd_defend_type_current, + sbuf256, + sizeof(sbuf256))); + if (n_acd_probe_announce(acd_data->nacd_probe, + _l3_acd_defend_type_to_nacd(acd_data->acd_defend_type_current)) + != 0) nm_assert_not_reached(); return; } @@ -2205,28 +2492,47 @@ handle_probe_done: static void _l3_acd_data_process_changes(NML3Cfg *self) { - gboolean acd_is_announcing = FALSE; - gboolean acd_is_pending = FALSE; + gboolean acd_is_pending = FALSE; + gboolean acd_busy = FALSE; AcdData *acd_data; + gint64 now_msec = 0; _l3_acd_data_prune(self, FALSE); c_list_for_each_entry (acd_data, &self->priv.p->acd_lst_head, acd_lst) { - _l3_acd_data_state_change(self, acd_data, ACD_STATE_CHANGE_MODE_POST_COMMIT, NULL); - if (acd_data->acd_state < ACD_STATE_PROBE_DONE) + _l3_acd_data_state_change(self, + acd_data, + ACD_STATE_CHANGE_MODE_POST_COMMIT, + NULL, + &now_msec); + if (acd_data->info.state <= NM_L3_ACD_ADDR_STATE_PROBING) acd_is_pending = TRUE; - else if (acd_data->acd_state >= ACD_STATE_ANNOUNCING - || (acd_data->acd_state >= ACD_STATE_PROBE_DONE && acd_data->probe_result)) - acd_is_announcing = TRUE; + if (acd_data->nacd_probe) + acd_busy = TRUE; } - self->priv.p->acd_is_pending = acd_is_pending; - self->priv.p->acd_is_announcing = acd_is_announcing; + self->priv.p->acd_is_pending = acd_is_pending; - if (!acd_is_pending && !acd_is_announcing) + if (!acd_busy) _l3_acd_nacd_instance_reset(self, NM_TERNARY_DEFAULT, FALSE); - _l3_acd_data_notify_acd_completed_all(self); + _nm_l3cfg_emit_signal_notify_acd_event_all(self); +} + +/*****************************************************************************/ + +const NML3AcdAddrInfo * +nm_l3cfg_get_acd_addr_info(NML3Cfg *self, in_addr_t addr) +{ + AcdData *acd_data; + + nm_assert(NM_IS_L3CFG(self)); + + acd_data = _l3_acd_data_find(self, addr); + if (!acd_data) + return NULL; + + return &acd_data->info; } /*****************************************************************************/ @@ -2238,7 +2544,7 @@ _l3_commit_on_idle_cb(gpointer user_data) nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source); - _LOGT("platform commit on idle"); + _LOGT("commit on idle"); _l3_commit(self, NM_L3_CFG_COMMIT_TYPE_AUTO, TRUE); return G_SOURCE_REMOVE; } @@ -2251,6 +2557,7 @@ nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self) if (self->priv.p->commit_on_idle_source) return; + _LOGT("commit on idle (scheduled)"); self->priv.p->commit_on_idle_source = nm_g_idle_source_new(G_PRIORITY_DEFAULT, _l3_commit_on_idle_cb, self, NULL); g_source_attach(self->priv.p->commit_on_idle_source, NULL); @@ -2275,7 +2582,7 @@ _l3_config_datas_find_next(GArray * l3_config_datas, for (i = start_idx; i < l3_config_datas->len; i++) { const L3ConfigData *l3_config_data = _l3_config_datas_at(l3_config_datas, i); - if (NM_IN_SET(needle_tag, NULL, l3_config_data->tag) + if (NM_IN_SET(needle_tag, NULL, l3_config_data->tag_confdata) && NM_IN_SET(needle_l3cd, NULL, l3_config_data->l3cd)) return i; } @@ -2294,54 +2601,15 @@ _l3_config_datas_get_sorted_cmp(gconstpointer p_a, gconstpointer p_b, gpointer u /* we sort the entries with higher priority (more important, lower numerical value) * first. */ - NM_CMP_FIELD(a, b, priority); + NM_CMP_FIELD(a, b, priority_confdata); /* if the priority is not unique, we sort them in the order they were added, * with the oldest first (lower numerical value). */ - NM_CMP_FIELD(a, b, pseudo_timestamp); + NM_CMP_FIELD(a, b, pseudo_timestamp_confdata); return nm_assert_unreachable_val(0); } -#define _l3_config_datas_get_sorted_a(l3_config_datas, out_infos, out_infos_len, out_infos_free) \ - G_STMT_START \ - { \ - GArray *const _l3_config_datas = (l3_config_datas); \ - const L3ConfigData *const **const _out_infos = (out_infos); \ - guint *const _out_infos_len = (out_infos_len); \ - const L3ConfigData ***const _out_infos_free = (out_infos_free); \ - gs_free const L3ConfigData **_infos_free = NULL; \ - const L3ConfigData ** _infos; \ - guint _l3_config_datas_len; \ - guint _i; \ - \ - _l3_config_datas_len = nm_g_array_len(_l3_config_datas); \ - \ - if (_l3_config_datas_len == 0) \ - _infos = NULL; \ - else if (_l3_config_datas_len < 300 / sizeof(_infos[0])) \ - _infos = g_alloca(_l3_config_datas_len * sizeof(_infos[0])); \ - else { \ - _infos_free = g_new(const L3ConfigData *, _l3_config_datas_len); \ - _infos = _infos_free; \ - } \ - for (_i = 0; _i < _l3_config_datas_len; _i++) \ - _infos[_i] = _l3_config_datas_at(_l3_config_datas, _i); \ - \ - if (_l3_config_datas_len > 1) { \ - g_qsort_with_data(_infos, \ - _l3_config_datas_len, \ - sizeof(_infos[0]), \ - _l3_config_datas_get_sorted_cmp, \ - NULL); \ - } \ - \ - *_out_infos = _infos; \ - *_out_infos_len = _l3_config_datas_len; \ - *_out_infos_free = g_steal_pointer(&_infos_free); \ - } \ - G_STMT_END - static void _l3_config_datas_remove_index_fast(GArray *arr, guint idx) { @@ -2376,7 +2644,7 @@ nm_l3cfg_mark_config_dirty(NML3Cfg *self, gconstpointer tag, gboolean dirty) if (idx < 0) return; - _l3_config_datas_at(self->priv.p->l3_config_datas, idx)->dirty = dirty; + _l3_config_datas_at(self->priv.p->l3_config_datas, idx)->dirty_confdata = dirty; idx++; } } @@ -2393,6 +2661,7 @@ nm_l3cfg_add_config(NML3Cfg * self, guint32 default_route_metric_6, guint32 default_route_penalty_4, guint32 default_route_penalty_6, + NML3AcdDefendType acd_defend_type, guint32 acd_timeout_msec, NML3ConfigMergeFlags merge_flags) { @@ -2405,6 +2674,14 @@ nm_l3cfg_add_config(NML3Cfg * self, nm_assert(l3cd); nm_assert(nm_l3_config_data_get_ifindex(l3cd) == self->priv.ifindex); + if (acd_timeout_msec > ACD_MAX_TIMEOUT_MSEC) + acd_timeout_msec = ACD_MAX_TIMEOUT_MSEC; + + nm_assert(NM_IN_SET(acd_defend_type, + NM_L3_ACD_DEFEND_TYPE_NEVER, + NM_L3_ACD_DEFEND_TYPE_ONCE, + NM_L3_ACD_DEFEND_TYPE_ALWAYS)); + nm_assert(default_route_metric_6 != 0u); /* IPv6 default route metric cannot be zero. */ if (default_route_table_4 == 0u) @@ -2434,12 +2711,11 @@ nm_l3cfg_add_config(NML3Cfg * self, if (l3_config_data->l3cd == l3cd) { nm_assert(idx == -1); idx = idx2; - continue; + idx2++; + } else { + changed = TRUE; + _l3_config_datas_remove_index_fast(self->priv.p->l3_config_datas, idx2); } - - changed = TRUE; - _l3_config_datas_remove_index_fast(self->priv.p->l3_config_datas, idx2); - idx2 = _l3_config_datas_find_next(self->priv.p->l3_config_datas, idx2, tag, NULL); if (idx2 < 0) break; @@ -2449,29 +2725,30 @@ nm_l3cfg_add_config(NML3Cfg * self, if (idx < 0) { l3_config_data = nm_g_array_append_new(self->priv.p->l3_config_datas, L3ConfigData); *l3_config_data = (L3ConfigData){ - .tag = tag, - .l3cd = nm_l3_config_data_ref_and_seal(l3cd), - .merge_flags = merge_flags, - .default_route_table_4 = default_route_table_4, - .default_route_table_6 = default_route_table_6, - .default_route_metric_4 = default_route_metric_4, - .default_route_metric_6 = default_route_metric_6, - .default_route_penalty_4 = default_route_penalty_4, - .default_route_penalty_6 = default_route_penalty_6, - .acd_timeout_msec = acd_timeout_msec, - .priority = priority, - .pseudo_timestamp = ++self->priv.p->pseudo_timestamp_counter, - .dirty = FALSE, + .tag_confdata = tag, + .l3cd = nm_l3_config_data_ref_and_seal(l3cd), + .merge_flags = merge_flags, + .default_route_table_4 = default_route_table_4, + .default_route_table_6 = default_route_table_6, + .default_route_metric_4 = default_route_metric_4, + .default_route_metric_6 = default_route_metric_6, + .default_route_penalty_4 = default_route_penalty_4, + .default_route_penalty_6 = default_route_penalty_6, + .acd_defend_type_confdata = acd_defend_type, + .acd_timeout_msec_confdata = acd_timeout_msec, + .priority_confdata = priority, + .pseudo_timestamp_confdata = ++self->priv.p->pseudo_timestamp_counter, + .dirty_confdata = FALSE, }; changed = TRUE; } else { - l3_config_data = _l3_config_datas_at(self->priv.p->l3_config_datas, idx); - l3_config_data->dirty = FALSE; - nm_assert(l3_config_data->tag == tag); + l3_config_data = _l3_config_datas_at(self->priv.p->l3_config_datas, idx); + l3_config_data->dirty_confdata = FALSE; + nm_assert(l3_config_data->tag_confdata == tag); nm_assert(l3_config_data->l3cd == l3cd); - if (l3_config_data->priority != priority) { - l3_config_data->priority = priority; - changed = TRUE; + if (l3_config_data->priority_confdata != priority) { + l3_config_data->priority_confdata = priority; + changed = TRUE; } if (l3_config_data->merge_flags != merge_flags) { l3_config_data->merge_flags = merge_flags; @@ -2501,12 +2778,18 @@ nm_l3cfg_add_config(NML3Cfg * self, l3_config_data->default_route_penalty_6 = default_route_penalty_6; changed = TRUE; } - if (l3_config_data->acd_timeout_msec != acd_timeout_msec) { - l3_config_data->acd_timeout_msec = acd_timeout_msec; - changed = TRUE; + if (l3_config_data->acd_defend_type_confdata != acd_defend_type) { + l3_config_data->acd_defend_type_confdata = acd_defend_type; + changed = TRUE; + } + if (l3_config_data->acd_timeout_msec_confdata != acd_timeout_msec) { + l3_config_data->acd_timeout_msec_confdata = acd_timeout_msec; + changed = TRUE; } } + nm_assert(l3_config_data->acd_defend_type_confdata == acd_defend_type); + if (changed) _l3_changed_configs_set_dirty(self); @@ -2537,7 +2820,8 @@ _l3cfg_remove_config(NML3Cfg * self, if (idx < 0) break; - if (only_dirty && !_l3_config_datas_at(self->priv.p->l3_config_datas, idx)->dirty) { + if (only_dirty + && !_l3_config_datas_at(self->priv.p->l3_config_datas, idx)->dirty_confdata) { idx++; continue; } @@ -2582,12 +2866,18 @@ typedef struct { } L3ConfigMergeHookAddObjData; static gboolean -_l3_hook_add_addr_cb(const NML3ConfigData *l3cd, const NMPObject *obj, gpointer user_data) +_l3_hook_add_addr_cb(const NML3ConfigData *l3cd, + const NMPObject * obj, + NMTernary * out_ip4acd_not_ready, + gpointer user_data) { const L3ConfigMergeHookAddObjData *hook_data = user_data; NML3Cfg * self = hook_data->self; AcdData * acd_data; in_addr_t addr; + gboolean acd_bad = FALSE; + + nm_assert(out_ip4acd_not_ready && *out_ip4acd_not_ready == NM_TERNARY_DEFAULT); if (NMP_OBJECT_GET_TYPE(obj) != NMP_OBJECT_TYPE_IP4_ADDRESS) return TRUE; @@ -2595,46 +2885,91 @@ _l3_hook_add_addr_cb(const NML3ConfigData *l3cd, const NMPObject *obj, gpointer addr = NMP_OBJECT_CAST_IP4_ADDRESS(obj)->address; if (ACD_ADDR_SKIP(addr)) - return TRUE; + goto out; acd_data = _l3_acd_data_find(self, addr); - nm_assert(acd_data); + + if (!acd_data) { + /* we don't yet track an ACD state for this address. That can only + * happend during _l3cfg_update_combined_config() with !to_commit, + * where we didn't update the ACD state. + * + * This means, unless you actually commit, nm_l3cfg_get_combined_l3cd(self, get_commited = FALSE) + * won't consider IPv4 addresses ready, that have no known ACD state yet. */ + nm_assert(self->priv.p->changed_configs_acd_state); + acd_bad = TRUE; + goto out; + } + nm_assert( _acd_track_data_is_not_dirty(_acd_data_find_track(acd_data, l3cd, obj, hook_data->tag))); - return _acd_data_probe_result_is_good(acd_data); + if (!NM_IN_SET(acd_data->info.state, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING)) + acd_bad = TRUE; + +out: + *out_ip4acd_not_ready = acd_bad ? NM_TERNARY_TRUE : NM_TERNARY_FALSE; + return TRUE; } static void _l3cfg_update_combined_config(NML3Cfg * self, gboolean to_commit, + gboolean reapply, const NML3ConfigData **out_old /* transfer reference */, - gboolean * out_changed_configs, gboolean * out_changed_combined_l3cd) { - nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; - nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - gs_free const L3ConfigData **l3_config_datas_free = NULL; - const L3ConfigData *const * l3_config_datas_sorted; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_commited_old = NULL; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + gs_free const L3ConfigData **l3_config_datas_free = NULL; + const L3ConfigData ** l3_config_datas_arr; guint l3_config_datas_len; guint i; + gboolean merged_changed = FALSE; + gboolean commited_changed = FALSE; nm_assert(NM_IS_L3CFG(self)); - nm_assert(!out_old || !*out_old); - NM_SET_OUT(out_changed_configs, self->priv.changed_configs); + NM_SET_OUT(out_changed_combined_l3cd, FALSE); - if (!self->priv.changed_configs) - goto out; + if (!self->priv.p->changed_configs_configs) { + if (!self->priv.p->changed_configs_acd_state) + goto out; + if (!to_commit) { + /* since we are not going to commit, we don't care about the + * ACD state. */ + goto out; + } + } + + self->priv.p->changed_configs_configs = FALSE; - self->priv.changed_configs = FALSE; + l3_config_datas_len = nm_g_array_len(self->priv.p->l3_config_datas); + l3_config_datas_arr = nm_malloc_maybe_a(300, + l3_config_datas_len * sizeof(l3_config_datas_arr[0]), + &l3_config_datas_free); + for (i = 0; i < l3_config_datas_len; i++) + l3_config_datas_arr[i] = _l3_config_datas_at(self->priv.p->l3_config_datas, i); - _l3_config_datas_get_sorted_a(self->priv.p->l3_config_datas, - &l3_config_datas_sorted, - &l3_config_datas_len, - &l3_config_datas_free); + if (l3_config_datas_len > 1) { + g_qsort_with_data(l3_config_datas_arr, + l3_config_datas_len, + sizeof(l3_config_datas_arr[0]), + _l3_config_datas_get_sorted_cmp, + NULL); + } - _l3_acd_data_add_all(self, l3_config_datas_sorted, l3_config_datas_len); + if (!to_commit) { + /* we are not going to commit these changes. Hence, we don't update the + * ACD states, but we need to remember that we have to on the next commit. */ + self->priv.p->changed_configs_acd_state = TRUE; + } else { + _l3_acd_data_add_all(self, l3_config_datas_arr, l3_config_datas_len, reapply); + self->priv.p->changed_configs_acd_state = FALSE; + } if (l3_config_datas_len > 0) { L3ConfigMergeHookAddObjData hook_data = { @@ -2645,12 +2980,12 @@ _l3cfg_update_combined_config(NML3Cfg * self, self->priv.ifindex); for (i = 0; i < l3_config_datas_len; i++) { - const L3ConfigData *l3cd_data = l3_config_datas_sorted[i]; + const L3ConfigData *l3cd_data = l3_config_datas_arr[i]; if (NM_FLAGS_HAS(l3cd_data->merge_flags, NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD)) continue; - hook_data.tag = l3cd_data->tag; + hook_data.tag = l3cd_data->tag_confdata; nm_l3_config_data_merge(l3cd, l3cd_data->l3cd, l3cd_data->merge_flags, @@ -2672,24 +3007,43 @@ _l3cfg_update_combined_config(NML3Cfg * self, l3cd_old = g_steal_pointer(&self->priv.p->combined_l3cd_merged); self->priv.p->combined_l3cd_merged = nm_l3_config_data_seal(g_steal_pointer(&l3cd)); - + merged_changed = TRUE; if (!to_commit) { NM_SET_OUT(out_old, g_steal_pointer(&l3cd_old)); NM_SET_OUT(out_changed_combined_l3cd, TRUE); - _LOGT("desired IP configuration changed"); } out: if (to_commit && self->priv.p->combined_l3cd_commited != self->priv.p->combined_l3cd_merged) { - nm_auto_unref_l3cd const NML3ConfigData *l3cd_commited_old = NULL; - l3cd_commited_old = g_steal_pointer(&self->priv.p->combined_l3cd_commited); self->priv.p->combined_l3cd_commited = nm_l3_config_data_ref(self->priv.p->combined_l3cd_merged); - + commited_changed = TRUE; NM_SET_OUT(out_old, g_steal_pointer(&l3cd_commited_old)); NM_SET_OUT(out_changed_combined_l3cd, TRUE); - _LOGT("desired IP configuration changed for commit"); + } + + if ((merged_changed || commited_changed) && _LOGT_ENABLED()) { + char sbuf256[256]; + char sbuf30[30]; + + _LOGT("IP configuration changed (merged=%c%s, commited=%c%s)", + merged_changed ? '>' : '=', + NM_HASH_OBFUSCATE_PTR_STR(self->priv.p->combined_l3cd_merged, sbuf256), + commited_changed ? '>' : '=', + NM_HASH_OBFUSCATE_PTR_STR(self->priv.p->combined_l3cd_commited, sbuf30)); + + if (merged_changed) { + nm_l3_config_data_log(self->priv.p->combined_l3cd_merged, + NULL, + nm_sprintf_buf(sbuf256, + "l3cfg[" NM_HASH_OBFUSCATE_PTR_FMT + ",ifindex=%d]: ", + NM_HASH_OBFUSCATE_PTR(self), + nm_l3cfg_get_ifindex(self)), + LOGL_TRACE, + _NMLOG_DOMAIN); + } } } @@ -2874,10 +3228,13 @@ out_prune: /*****************************************************************************/ static gboolean -_l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) +_l3_commit_one(NML3Cfg * self, + int addr_family, + NML3CfgCommitType commit_type, + gboolean changed_combined_l3cd, + const NML3ConfigData *l3cd_old) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); - nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; + const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_ptrarray GPtrArray *addresses = NULL; gs_unref_ptrarray GPtrArray *routes = NULL; gs_unref_ptrarray GPtrArray *addresses_prune = NULL; @@ -2885,8 +3242,6 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) gs_unref_ptrarray GPtrArray *routes_temporary_not_available_arr = NULL; NMIPRouteTableSyncMode route_table_sync = NM_IP_ROUTE_TABLE_SYNC_MODE_NONE; gboolean final_failure_for_temporary_not_available = FALSE; - gboolean changed_combined_l3cd; - gboolean changed_configs; char sbuf_commit_type[50]; gboolean success = TRUE; @@ -2902,8 +3257,6 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) nm_utils_addr_family_to_char(addr_family), _l3_cfg_commit_type_to_string(commit_type, sbuf_commit_type, sizeof(sbuf_commit_type))); - _l3cfg_update_combined_config(self, TRUE, &l3cd_old, &changed_configs, &changed_combined_l3cd); - if (changed_combined_l3cd) { /* our combined configuration changed. We may track entries in externally_removed_objs_hash, * which are not longer to be considered by our configuration. We need to forget about them. */ @@ -2916,29 +3269,40 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) } if (self->priv.p->combined_l3cd_commited) { + GHashTable * externally_removed_objs_hash; NMDedupMultiFcnSelectPredicate predicate; + const NMDedupMultiHeadEntry * head_entry; if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY - && self->priv.p->externally_removed_objs_cnt_addresses_x[IS_IPv4] > 0) - predicate = _l3cfg_externally_removed_objs_filter; - else - predicate = NULL; - addresses = nm_dedup_multi_objs_to_ptr_array_head( - nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, - NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)), - predicate, - self->priv.p->externally_removed_objs_hash); + && self->priv.p->externally_removed_objs_cnt_addresses_x[IS_IPv4] > 0) { + predicate = _l3cfg_externally_removed_objs_filter; + externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash; + } else { + if (IS_IPv4) + predicate = _l3cfg_externally_removed_objs_filter; + else + predicate = NULL; + externally_removed_objs_hash = NULL; + } + head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, + NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)); + addresses = nm_dedup_multi_objs_to_ptr_array_head(head_entry, + predicate, + externally_removed_objs_hash); if (commit_type != NM_L3_CFG_COMMIT_TYPE_REAPPLY - && self->priv.p->externally_removed_objs_cnt_routes_x[IS_IPv4] > 0) - predicate = _l3cfg_externally_removed_objs_filter; - else - predicate = NULL; - routes = nm_dedup_multi_objs_to_ptr_array_head( - nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, - NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)), - predicate, - self->priv.p->externally_removed_objs_hash); + && self->priv.p->externally_removed_objs_cnt_routes_x[IS_IPv4] > 0) { + predicate = _l3cfg_externally_removed_objs_filter; + externally_removed_objs_hash = self->priv.p->externally_removed_objs_hash; + } else { + predicate = NULL; + externally_removed_objs_hash = NULL; + } + head_entry = nm_l3_config_data_lookup_objs(self->priv.p->combined_l3cd_commited, + NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)); + routes = nm_dedup_multi_objs_to_ptr_array_head(head_entry, + predicate, + externally_removed_objs_hash); route_table_sync = nm_l3_config_data_get_route_table_sync(self->priv.p->combined_l3cd_commited, @@ -2958,22 +3322,13 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) self->priv.ifindex, route_table_sync); } else if (commit_type == NM_L3_CFG_COMMIT_TYPE_UPDATE) { - /* during update, we do a cross with the previous configuration. - * - * Of course, if an entry is both to be pruned and to be added, then - * the latter wins. So, this works just nicely. */ - if (l3cd_old) { - const NMDedupMultiHeadEntry *head_entry; - - head_entry = - nm_l3_config_data_lookup_objs(l3cd_old, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4)); - addresses_prune = nm_dedup_multi_objs_to_ptr_array_head(head_entry, NULL, NULL); - - head_entry = nm_l3_config_data_lookup_objs(l3cd_old, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4)); - addresses_prune = nm_dedup_multi_objs_to_ptr_array_head(head_entry, NULL, NULL); - } + addresses_prune = nm_g_ptr_array_ref(self->priv.p->last_addresses_x[IS_IPv4]); + routes_prune = nm_g_ptr_array_ref(self->priv.p->last_routes_x[IS_IPv4]); } + nm_g_ptr_array_set(&self->priv.p->last_addresses_x[IS_IPv4], addresses); + nm_g_ptr_array_set(&self->priv.p->last_routes_x[IS_IPv4], routes); + /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ip6_privacy(). */ /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ndisc_*(). */ /* FIXME(l3cfg): need to honor and set nm_l3_config_data_get_ip6_mtu(). */ @@ -3008,8 +3363,10 @@ _l3_commit_one(NML3Cfg *self, int addr_family, NML3CfgCommitType commit_type) static void _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) { - gboolean commit_type_detected = FALSE; - char sbuf_ct[30]; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_old = NULL; + gboolean commit_type_detected = FALSE; + char sbuf_ct[30]; + gboolean changed_combined_l3cd; g_return_if_fail(NM_IS_L3CFG(self)); nm_assert(NM_IN_SET(commit_type, @@ -3018,6 +3375,7 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) NM_L3_CFG_COMMIT_TYPE_ASSUME, NM_L3_CFG_COMMIT_TYPE_UPDATE, NM_L3_CFG_COMMIT_TYPE_REAPPLY)); + nm_assert(self->priv.p->commit_reentrant_count == 0); switch (commit_type) { case NM_L3_CFG_COMMIT_TYPE_AUTO: @@ -3043,7 +3401,7 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) break; } - _LOGT("platform-commit %s%s%s", + _LOGT("commit %s%s%s", _l3_cfg_commit_type_to_string(commit_type, sbuf_ct, sizeof(sbuf_ct)), commit_type_detected ? " (auto)" : "", is_idle ? " (idle handler)" : ""); @@ -3051,18 +3409,29 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle) if (commit_type == NM_L3_CFG_COMMIT_TYPE_NONE) return; + self->priv.p->commit_reentrant_count++; + nm_clear_g_source_inst(&self->priv.p->commit_on_idle_source); if (commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY) _l3cfg_externally_removed_objs_drop(self); + _l3cfg_update_combined_config(self, + TRUE, + commit_type == NM_L3_CFG_COMMIT_TYPE_REAPPLY, + &l3cd_old, + &changed_combined_l3cd); + /* FIXME(l3cfg): handle items currently not configurable in kernel. */ - _l3_commit_one(self, AF_INET, commit_type); - _l3_commit_one(self, AF_INET6, commit_type); + _l3_commit_one(self, AF_INET, commit_type, changed_combined_l3cd, l3cd_old); + _l3_commit_one(self, AF_INET6, commit_type, changed_combined_l3cd, l3cd_old); _l3_acd_data_process_changes(self); + nm_assert(self->priv.p->commit_reentrant_count == 1); + self->priv.p->commit_reentrant_count--; + _nm_l3cfg_emit_signal_notify_simple(self, NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT); } @@ -3141,7 +3510,7 @@ nm_l3cfg_commit_type_register(NML3Cfg * self, linked = FALSE; c_list_for_each_entry (h, &self->priv.p->commit_type_lst_head, commit_type_lst) { if (handle->commit_type >= h->commit_type) { - c_list_link_before(&self->priv.p->commit_type_lst_head, &handle->commit_type_lst); + c_list_link_before(&h->commit_type_lst, &handle->commit_type_lst); linked = TRUE; break; } @@ -3178,7 +3547,7 @@ nm_l3cfg_get_combined_l3cd(NML3Cfg *self, gboolean get_commited) if (get_commited) return self->priv.p->combined_l3cd_commited; - _l3cfg_update_combined_config(self, FALSE, NULL, NULL, NULL); + _l3cfg_update_combined_config(self, FALSE, FALSE, NULL, NULL); return self->priv.p->combined_l3cd_merged; } @@ -3220,8 +3589,7 @@ nm_l3cfg_has_commited_ip6_addresses_pending_dad(NML3Cfg *self) nmp_lookup_init_object(&plat_lookup, NMP_OBJECT_TYPE_IP6_ADDRESS, self->priv.ifindex); - nm_platform_iter_obj_for_each(&iter, self->priv.platform, &plat_lookup, &plat_obj) - { + nm_platform_iter_obj_for_each (&iter, self->priv.platform, &plat_lookup, &plat_obj) { const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj); const NMDedupMultiEntry * l3cd_entry; @@ -3243,6 +3611,47 @@ nm_l3cfg_has_commited_ip6_addresses_pending_dad(NML3Cfg *self) /*****************************************************************************/ +NML3IPv4LL * +nm_l3cfg_get_ipv4ll(NML3Cfg *self) +{ + g_return_val_if_fail(NM_IS_L3CFG(self), NULL); + + return self->priv.p->ipv4ll; +} + +NML3IPv4LL * +nm_l3cfg_access_ipv4ll(NML3Cfg *self) +{ + g_return_val_if_fail(NM_IS_L3CFG(self), NULL); + + if (self->priv.p->ipv4ll) + return nm_l3_ipv4ll_ref(self->priv.p->ipv4ll); + + /* We return the reference. But the NML3IPv4LL instance + * will call _nm_l3cfg_unregister_ipv4ll() when it gets + * destroyed. + * + * We don't have weak references, but NML3Cfg and NML3IPv4LL + * cooperate to handle this reference. */ + self->priv.p->ipv4ll = nm_l3_ipv4ll_new(self); + return self->priv.p->ipv4ll; +} + +void +_nm_l3cfg_unregister_ipv4ll(NML3Cfg *self) +{ + nm_assert(NM_IS_L3CFG(self)); + + /* we don't own the refernce to "self->priv.p->ipv4ll", but + * when that instance gets destroyed, we get called back to + * forget about it. Basically, it's like a weak pointer. */ + + nm_assert(self->priv.p->ipv4ll); + self->priv.p->ipv4ll = NULL; +} + +/*****************************************************************************/ + static void set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { @@ -3273,7 +3682,7 @@ nm_l3cfg_init(NML3Cfg *self) self->priv.p = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_L3CFG, NML3CfgPrivate); c_list_init(&self->priv.p->acd_lst_head); - c_list_init(&self->priv.p->acd_notify_complete_lst_head); + c_list_init(&self->priv.p->acd_event_notify_lst_head); c_list_init(&self->priv.p->commit_type_lst_head); } @@ -3310,6 +3719,7 @@ finalize(GObject *object) NML3Cfg *self = NM_L3CFG(object); nm_assert(!self->priv.p->l3_config_datas); + nm_assert(!self->priv.p->ipv4ll); nm_assert(c_list_is_empty(&self->priv.p->commit_type_lst_head)); @@ -3320,7 +3730,7 @@ finalize(GObject *object) _l3_acd_data_prune(self, TRUE); nm_assert(c_list_is_empty(&self->priv.p->acd_lst_head)); - nm_assert(c_list_is_empty(&self->priv.p->acd_notify_complete_lst_head)); + nm_assert(c_list_is_empty(&self->priv.p->acd_event_notify_lst_head)); nm_assert(nm_g_hash_table_size(self->priv.p->acd_lst_hash) == 0); nm_clear_pointer(&self->priv.p->acd_lst_hash, g_hash_table_unref); @@ -3328,6 +3738,11 @@ finalize(GObject *object) nm_clear_g_source_inst(&self->priv.p->nacd_source); nm_clear_g_source_inst(&self->priv.p->nacd_instance_ensure_retry); + nm_clear_pointer(&self->priv.p->last_addresses_4, g_ptr_array_unref); + nm_clear_pointer(&self->priv.p->last_addresses_6, g_ptr_array_unref); + nm_clear_pointer(&self->priv.p->last_routes_4, g_ptr_array_unref); + nm_clear_pointer(&self->priv.p->last_routes_6, g_ptr_array_unref); + nm_clear_g_source(&self->priv.p->routes_temporary_not_available_id); nm_clear_pointer(&self->priv.p->routes_temporary_not_available_hash, g_hash_table_unref); diff --git a/src/nm-l3cfg.h b/src/core/nm-l3cfg.h index 9f957ae1..5cfc93f6 100644 --- a/src/nm-l3cfg.h +++ b/src/core/nm-l3cfg.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef __NM_L3CFG_H__ #define __NM_L3CFG_H__ @@ -6,6 +6,9 @@ #include "platform/nmp-object.h" #include "nm-l3-config-data.h" +#define NM_L3CFG_CONFIG_PRIORITY_IPV4LL 0 +#define NM_ACD_TIMEOUT_RFC5227_MSEC 9000u + #define NM_TYPE_L3CFG (nm_l3cfg_get_type()) #define NM_L3CFG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_L3CFG, NML3Cfg)) #define NM_L3CFG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_L3CFG, NML3CfgClass)) @@ -18,10 +21,76 @@ #define NM_L3CFG_SIGNAL_NOTIFY "l3cfg-notify" +typedef enum _nm_packed { + NM_L3_ACD_DEFEND_TYPE_NONE, + NM_L3_ACD_DEFEND_TYPE_NEVER, + NM_L3_ACD_DEFEND_TYPE_ONCE, + NM_L3_ACD_DEFEND_TYPE_ALWAYS, +} NML3AcdDefendType; + +typedef enum _nm_packed { + NM_L3_ACD_ADDR_STATE_INIT, + NM_L3_ACD_ADDR_STATE_PROBING, + NM_L3_ACD_ADDR_STATE_USED, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING, + NM_L3_ACD_ADDR_STATE_CONFLICT, + NM_L3_ACD_ADDR_STATE_EXTERNAL_REMOVED, +} NML3AcdAddrState; + +typedef struct { + const NMPObject * obj; + const NML3ConfigData *l3cd; + gconstpointer tag; + + struct { + guint32 acd_timeout_msec_track; + NML3AcdDefendType acd_defend_type_track; + bool acd_dirty_track : 1; + bool acd_failed_notified_track : 1; + } _priv; + +} NML3AcdAddrTrackInfo; + +typedef struct { + in_addr_t addr; + guint n_track_infos; + NML3AcdAddrState state; + NML3Cfg * l3cfg; + const NML3AcdAddrTrackInfo *track_infos; +} NML3AcdAddrInfo; + +static inline const NML3AcdAddrTrackInfo * +nm_l3_acd_addr_info_find_track_info(const NML3AcdAddrInfo *addr_info, + gconstpointer tag, + const NML3ConfigData * l3cd, + const NMPObject * obj) +{ + guint i; + const NML3AcdAddrTrackInfo *ti; + + nm_assert(addr_info); + + /* we always expect that the number n_track_infos is reasonably small. Hence, + * a naive linear search is simplest and fastest (e.g. we don't have a hash table). */ + + for (i = 0, ti = addr_info->track_infos; i < addr_info->n_track_infos; i++, ti++) { + if (l3cd && ti->l3cd != l3cd) + continue; + if (tag && ti->tag != tag) + continue; + if (obj && ti->obj != obj) + continue; + return ti; + } + + return NULL; +} + typedef enum { NM_L3_CONFIG_NOTIFY_TYPE_ROUTES_TEMPORARY_NOT_AVAILABLE_EXPIRED, - NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED, + NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT, /* emitted at the end of nm_l3cfg_platform_commit(). */ NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT, @@ -38,24 +107,19 @@ typedef enum { * notifications without also subscribing directly to the platform. */ NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE, + NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT, + _NM_L3_CONFIG_NOTIFY_TYPE_NUM, } NML3ConfigNotifyType; -typedef struct { - const NMPObject * obj; - const NML3ConfigData *l3cd; - gconstpointer tag; -} NML3ConfigNotifyPayloadAcdFailedSource; +struct _NML3IPv4LL; typedef struct { NML3ConfigNotifyType notify_type; union { struct { - in_addr_t addr; - guint sources_len; - bool probe_result : 1; - const NML3ConfigNotifyPayloadAcdFailedSource *sources; - } acd_completed; + NML3AcdAddrInfo info; + } acd_event; struct { const NMPObject * obj; @@ -65,6 +129,10 @@ typedef struct { struct { guint32 obj_type_flags; } platform_change_on_idle; + + struct { + struct _NML3IPv4LL *ipv4ll; + } ipv4ll_event; }; } NML3ConfigNotifyData; @@ -79,7 +147,6 @@ struct _NML3Cfg { const NMPObject * plobj; const NMPObject * plobj_next; int ifindex; - bool changed_configs : 1; } priv; }; @@ -205,6 +272,7 @@ gboolean nm_l3cfg_add_config(NML3Cfg * self, guint32 default_route_metric_6, guint32 default_route_penalty_4, guint32 default_route_penalty_6, + NML3AcdDefendType acd_defend_type, guint32 acd_timeout_msec, NML3ConfigMergeFlags merge_flags); @@ -250,6 +318,10 @@ void nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self); /*****************************************************************************/ +const NML3AcdAddrInfo *nm_l3cfg_get_acd_addr_info(NML3Cfg *self, in_addr_t addr); + +/*****************************************************************************/ + NML3CfgCommitType nm_l3cfg_commit_type_get(NML3Cfg *self); typedef struct _NML3CfgCommitTypeHandle NML3CfgCommitTypeHandle; @@ -273,4 +345,12 @@ gboolean nm_l3cfg_has_commited_ip6_addresses_pending_dad(NML3Cfg *self); /*****************************************************************************/ +struct _NML3IPv4LL *nm_l3cfg_get_ipv4ll(NML3Cfg *self); + +struct _NML3IPv4LL *nm_l3cfg_access_ipv4ll(NML3Cfg *self); + +void _nm_l3cfg_unregister_ipv4ll(NML3Cfg *self); + +/*****************************************************************************/ + #endif /* __NM_L3CFG_H__ */ diff --git a/src/nm-manager.c b/src/core/nm-manager.c index 46f81c7c..5a6e05a9 100644 --- a/src/nm-manager.c +++ b/src/core/nm-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2009 Novell, Inc. * Copyright (C) 2007 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-manager.h" @@ -102,6 +102,7 @@ enum { ACTIVE_CONNECTION_ADDED, ACTIVE_CONNECTION_REMOVED, CONFIGURE_QUIT, + DEVICE_IFINDEX_CHANGED, LAST_SIGNAL }; @@ -142,7 +143,7 @@ typedef struct { GArray *capabilities; - CList active_connections_lst_head; + CList active_connections_lst_head; /* Oldest ACs at the beginning */ CList async_op_lst_head; guint ac_cleanup_id; NMActiveConnection *primary_connection; @@ -941,7 +942,7 @@ active_connection_add(NMManager *self, NMActiveConnection *active) nm_assert(NM_IS_ACTIVE_CONNECTION(active)); nm_assert(!c_list_is_linked(&active->active_connections_lst)); - c_list_link_front(&priv->active_connections_lst_head, &active->active_connections_lst); + c_list_link_tail(&priv->active_connections_lst_head, &active->active_connections_lst); g_object_ref(active); g_signal_connect(active, @@ -987,7 +988,7 @@ active_connection_find( nm_assert(!sett_conn || NM_IS_SETTINGS_CONNECTION(sett_conn)); nm_assert(!out_all_matching || !*out_all_matching); - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + c_list_for_each_entry_prev (ac, &priv->active_connections_lst_head, active_connections_lst) { NMSettingsConnection *ac_conn; ac_conn = nm_active_connection_get_settings_connection(ac); @@ -1013,8 +1014,37 @@ active_connection_find( g_ptr_array_add(all, g_object_ref(ac)); } - if (!best_ac) - return NULL; + if (!best_ac) { + AsyncOpData *async_op_data; + + c_list_for_each_entry (async_op_data, &priv->async_op_lst_head, async_op_lst) { + NMSettingsConnection *ac_conn; + + ac = async_op_data->ac_auth.active; + ac_conn = nm_active_connection_get_settings_connection(ac); + if (sett_conn && sett_conn != ac_conn) + continue; + if (uuid && !nm_streq0(uuid, nm_settings_connection_get_uuid(ac_conn))) + continue; + + if (!out_all_matching) + return ac; + + if (!best_ac) { + best_ac = ac; + continue; + } + + if (!all) { + all = g_ptr_array_new_with_free_func(g_object_unref); + g_ptr_array_add(all, g_object_ref(best_ac)); + } + g_ptr_array_add(all, g_object_ref(ac)); + } + + if (!best_ac) + return NULL; + } /* as an optimization, we only allocate out_all_matching, if there are more * than one result. If there is only one result, we only return the single @@ -2495,16 +2525,7 @@ nm_manager_device_auth_request(NMManager * self, &error)) goto fail_on_idle; - /* Validate the request */ chain = nm_auth_chain_new_subject(subject, context, device_auth_done_cb, self); - if (!chain) { - g_set_error(&error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto fail_on_idle; - } - if (cancellable) nm_auth_chain_set_cancellable(chain, cancellable); @@ -4907,11 +4928,11 @@ _internal_activate_device(NMManager *self, NMActiveConnection *active, GError ** if (master_device) { g_prefix_error(error, "Master device '%s' can't be activated: ", - nm_device_get_ip_iface(device)); + nm_device_get_ip_iface(master_device)); } else { g_prefix_error(error, "Master connection '%s' can't be activated: ", - nm_settings_connection_get_id(sett_conn)); + nm_settings_connection_get_id(master_connection)); } return FALSE; } @@ -5184,6 +5205,7 @@ _internal_activation_auth_done(NMManager * self, return; fail: + _delete_volatile_connection_do(self, nm_active_connection_get_settings_connection(active)); nm_assert(error_desc || error); nm_active_connection_set_state_fail(active, NM_ACTIVE_CONNECTION_STATE_REASON_UNKNOWN, @@ -5452,6 +5474,8 @@ _activation_auth_done(NMManager * self, return; fail: + _delete_volatile_connection_do(self, connection); + nm_audit_log_connection_op(NM_AUDIT_OP_CONN_ACTIVATE, connection, FALSE, @@ -6038,15 +6062,7 @@ impl_manager_deactivate_connection(NMDBusObject * obj, &error)) goto done; - /* Validate the user request */ chain = nm_auth_chain_new_subject(subject, invocation, deactivate_net_auth_done_cb, self); - if (!chain) { - error = g_error_new_literal(NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto done; - } - c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); nm_auth_chain_set_data(chain, "path", g_strdup(active_path), g_free); nm_auth_chain_add_call(chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); @@ -7435,10 +7451,11 @@ auth_mgr_changed(NMAuthManager *auth_manager, gpointer user_data) #define KERN_RFKILL_TYPE_WLAN 1 #define KERN_RFKILL_TYPE_WWAN 5 struct rfkill_event { - __u32 idx; - __u8 type; - __u8 op; - __u8 soft, hard; + uint32_t idx; + uint8_t type; + uint8_t op; + uint8_t soft; + uint8_t hard; } _nm_packed; static void @@ -7566,6 +7583,14 @@ periodic_update_active_connection_timestamps(gpointer user_data) return G_SOURCE_CONTINUE; } +void +nm_manager_unblock_failed_ovs_interfaces(NMManager *self) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE(self); + + nm_policy_unblock_failed_ovs_interfaces(priv->policy); +} + /*****************************************************************************/ void @@ -7598,6 +7623,12 @@ nm_manager_set_capability(NMManager *self, NMCapability cap) _notify(self, PROP_CAPABILITIES); } +void +nm_manager_emit_device_ifindex_changed(NMManager *self, NMDevice *device) +{ + g_signal_emit(self, signals[DEVICE_IFINDEX_CHANGED], 0, device); +} + /*****************************************************************************/ NM_DEFINE_SINGLETON_REGISTER(NMManager); @@ -7857,7 +7888,9 @@ get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) break; case PROP_ACTIVE_CONNECTIONS: ptrarr = g_ptr_array_new(); - c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) { + c_list_for_each_entry_prev (ac, + &priv->active_connections_lst_head, + active_connections_lst) { path = nm_dbus_object_get_path(NM_DBUS_OBJECT(ac)); if (path) g_ptr_array_add(ptrarr, g_strdup(path)); @@ -8649,4 +8682,15 @@ nm_manager_class_init(NMManagerClass *manager_class) NULL, G_TYPE_NONE, 0); + + signals[DEVICE_IFINDEX_CHANGED] = g_signal_new(NM_MANAGER_DEVICE_IFINDEX_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + NM_TYPE_DEVICE); } diff --git a/src/nm-manager.h b/src/core/nm-manager.h index 75f8a673..7a8b3a1e 100644 --- a/src/nm-manager.h +++ b/src/core/nm-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2010 Red Hat, Inc. @@ -50,6 +50,7 @@ /* Signals */ #define NM_MANAGER_DEVICE_ADDED "device-added" #define NM_MANAGER_DEVICE_REMOVED "device-removed" +#define NM_MANAGER_DEVICE_IFINDEX_CHANGED "device-ifindex-changed" #define NM_MANAGER_USER_PERMISSIONS_CHANGED "user-permissions-changed" #define NM_MANAGER_ACTIVE_CONNECTION_ADDED "active-connection-added" @@ -72,6 +73,7 @@ NMState nm_manager_get_state(NMManager *manager); const CList *nm_manager_get_active_connections(NMManager *manager); +/* From least recently activated */ #define nm_manager_for_each_active_connection(manager, iter, tmp_list) \ for (tmp_list = nm_manager_get_active_connections(manager), \ iter = c_list_entry(tmp_list->next, NMActiveConnection, active_connections_lst); \ @@ -86,6 +88,22 @@ const CList *nm_manager_get_active_connections(NMManager *manager); NMActiveConnection, \ active_connections_lst)) +/* From most recently activated */ +#define nm_manager_for_each_active_connection_prev(manager, iter, tmp_list) \ + for (tmp_list = nm_manager_get_active_connections(manager), \ + iter = c_list_entry(tmp_list->prev, NMActiveConnection, active_connections_lst); \ + ({ \ + const gboolean _has_prev = (&iter->active_connections_lst != tmp_list); \ + \ + if (!_has_prev) \ + iter = NULL; \ + _has_prev; \ + }); \ + iter = c_list_entry(iter->active_connections_lst.prev, \ + NMActiveConnection, \ + active_connections_lst)) + +/* From least recently activated */ #define nm_manager_for_each_active_connection_safe(manager, iter, tmp_list, iter_safe) \ for (tmp_list = nm_manager_get_active_connections(manager), iter_safe = tmp_list->next; ({ \ if (iter_safe != tmp_list) { \ @@ -163,6 +181,7 @@ gboolean nm_manager_deactivate_connection(NMManager * manager, GError ** error); void nm_manager_set_capability(NMManager *self, NMCapability cap); +void nm_manager_emit_device_ifindex_changed(NMManager *self, NMDevice *device); NMDevice *nm_manager_get_device(NMManager *self, const char *ifname, NMDeviceType device_type); gboolean nm_manager_remove_device(NMManager *self, const char *ifname, NMDeviceType device_type); @@ -192,4 +211,6 @@ void nm_manager_device_auth_request(NMManager * self, NMManagerDeviceAuthRequestFunc callback, gpointer user_data); +void nm_manager_unblock_failed_ovs_interfaces(NMManager *self); + #endif /* __NETWORKMANAGER_MANAGER_H__ */ diff --git a/src/nm-netns.c b/src/core/nm-netns.c index 2970e45c..88ea09b6 100644 --- a/src/nm-netns.c +++ b/src/core/nm-netns.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-netns.h" @@ -14,7 +14,7 @@ #include "nm-core-internal.h" #include "nm-l3cfg.h" #include "platform/nm-platform.h" -#include "platform/nmp-netns.h" +#include "nm-platform/nmp-netns.h" #include "platform/nmp-rules-manager.h" /*****************************************************************************/ @@ -126,6 +126,19 @@ _l3cfg_weak_notify(gpointer data, GObject *where_the_object_was) } NML3Cfg * +nm_netns_get_l3cfg(NMNetns *self, int ifindex) +{ + NMNetnsPrivate *priv; + + g_return_val_if_fail(NM_IS_NETNS(self), NULL); + g_return_val_if_fail(ifindex > 0, NULL); + + priv = NM_NETNS_GET_PRIVATE(self); + + return g_hash_table_lookup(priv->l3cfgs, &ifindex); +} + +NML3Cfg * nm_netns_access_l3cfg(NMNetns *self, int ifindex) { NMNetnsPrivate *priv; @@ -453,7 +466,7 @@ dispose(GObject *object) g_signal_handlers_disconnect_by_data(priv->platform, &priv->_self_signal_user_data); g_clear_object(&priv->platform); - g_clear_pointer(&priv->l3cfgs, g_hash_table_unref); + nm_clear_pointer(&priv->l3cfgs, g_hash_table_unref); nm_clear_pointer(&priv->rules_manager, nmp_rules_manager_unref); diff --git a/src/nm-netns.h b/src/core/nm-netns.h index bb0c955e..aab3b520 100644 --- a/src/nm-netns.h +++ b/src/core/nm-netns.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ @@ -6,6 +6,8 @@ #ifndef __NM_NETNS_H__ #define __NM_NETNS_H__ +#include "nm-platform/nmp-base.h" + #define NM_TYPE_NETNS (nm_netns_get_type()) #define NM_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_NETNS, NMNetns)) #define NM_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_NETNS, NMNetnsClass)) @@ -31,6 +33,8 @@ struct _NMDedupMultiIndex *nm_netns_get_multi_idx(NMNetns *self); #define NM_NETNS_GET (nm_netns_get()) +NML3Cfg *nm_netns_get_l3cfg(NMNetns *self, int ifindex); + NML3Cfg *nm_netns_access_l3cfg(NMNetns *netns, int ifindex); /*****************************************************************************/ diff --git a/src/nm-pacrunner-manager.c b/src/core/nm-pacrunner-manager.c index 0fb31984..b58aef06 100644 --- a/src/nm-pacrunner-manager.c +++ b/src/core/nm-pacrunner-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-pacrunner-manager.h" @@ -126,11 +126,13 @@ NM_AUTO_DEFINE_FCN0(NMPacrunnerConfId *, _nm_auto_unref_conf_id, conf_id_unref); static void get_ip_domains(GPtrArray *domains, NMIPConfig *ip_config) { - NMDedupMultiIter ipconf_iter; - char * cidr; - guint i, num; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - int addr_family; + NMDedupMultiIter ipconf_iter; + char * cidr; + guint i, num; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + int addr_family; + const NMPlatformIPAddress *address; + const NMPlatformIPRoute * routes; if (!ip_config) return; @@ -145,47 +147,20 @@ get_ip_domains(GPtrArray *domains, NMIPConfig *ip_config) for (i = 0; i < num; i++) g_ptr_array_add(domains, g_strdup(nm_ip_config_get_domain(ip_config, i))); - if (addr_family == AF_INET) { - const NMPlatformIP4Address *address; - - nm_ip_config_iter_ip4_address_for_each (&ipconf_iter, (NMIP4Config *) ip_config, &address) { - cidr = g_strdup_printf("%s/%u", - _nm_utils_inet4_ntop(address->address, sbuf), - address->plen); - g_ptr_array_add(domains, cidr); - } - } else { - const NMPlatformIP6Address *address; - - nm_ip_config_iter_ip6_address_for_each (&ipconf_iter, (NMIP6Config *) ip_config, &address) { - cidr = g_strdup_printf("%s/%u", - _nm_utils_inet6_ntop(&address->address, sbuf), - address->plen); - g_ptr_array_add(domains, cidr); - } + nm_ip_config_iter_ip_address_for_each (&ipconf_iter, ip_config, &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); } - if (addr_family == AF_INET) { - const NMPlatformIP4Route *routes; - - nm_ip_config_iter_ip4_route_for_each (&ipconf_iter, (NMIP4Config *) ip_config, &routes) { - if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(routes)) - continue; - cidr = - g_strdup_printf("%s/%u", _nm_utils_inet4_ntop(routes->network, sbuf), routes->plen); - g_ptr_array_add(domains, cidr); - } - } else { - const NMPlatformIP6Route *routes; - - nm_ip_config_iter_ip6_route_for_each (&ipconf_iter, (NMIP6Config *) ip_config, &routes) { - if (NM_PLATFORM_IP_ROUTE_IS_DEFAULT(routes)) - continue; - cidr = g_strdup_printf("%s/%u", - _nm_utils_inet6_ntop(&routes->network, sbuf), - routes->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)) + continue; + cidr = g_strdup_printf("%s/%u", + nm_utils_inet_ntop(addr_family, routes->network_ptr, sbuf), + routes->plen); + g_ptr_array_add(domains, cidr); } } diff --git a/src/nm-pacrunner-manager.h b/src/core/nm-pacrunner-manager.h index b3c3bdb7..fd40f120 100644 --- a/src/nm-pacrunner-manager.h +++ b/src/core/nm-pacrunner-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. * Copyright (C) 2016 - 2017 Red Hat, Inc. diff --git a/src/nm-policy.c b/src/core/nm-policy.c index 038b89cf..db4983f8 100644 --- a/src/nm-policy.c +++ b/src/core/nm-policy.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2013 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-policy.h" @@ -64,12 +64,6 @@ typedef struct { NMActiveConnection *default_ac4, *activating_ac4; NMActiveConnection *default_ac6, *activating_ac6; - struct { - GInetAddress *addr; - GResolver * resolver; - GCancellable *cancellable; - } lookup; - NMDnsManager *dns_manager; gulong config_changed_id; @@ -82,8 +76,10 @@ typedef struct { char * cur_hostname; /* hostname we want to assign */ char * last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */ - gboolean changing_hostname; /* hostname set operation still in progress */ - gboolean dhcp_hostname; /* current hostname was set from dhcp */ + + bool changing_hostname : 1; /* hostname set operation in progress */ + bool dhcp_hostname : 1; /* current hostname was set from dhcp */ + bool updating_dns : 1; GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */ } NMPolicyPrivate; @@ -117,6 +113,8 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv) /*****************************************************************************/ #define _NMLOG_PREFIX_NAME "policy" +#undef _NMLOG_ENABLED +#define _NMLOG_ENABLED(level, domain) (nm_logging_enabled((level), (domain))) #define _NMLOG(level, domain, ...) \ G_STMT_START \ { \ @@ -131,6 +129,7 @@ _PRIV_TO_SELF(NMPolicyPrivate *priv) /*****************************************************************************/ +static void update_system_hostname(NMPolicy *self, const char *msg); static void schedule_activate_all(NMPolicy *self); static void schedule_activate_check(NMPolicy *self, NMDevice *device); static NMDevice *get_default_device(NMPolicy *self, int addr_family); @@ -359,11 +358,11 @@ device_ip6_prefix_delegated(NMDevice *device, NMPlatformIP6Address *prefix, gpoi delegation->device = device; delegation->prefix = *prefix; - /* The newly activated connections are added to the list beginning, - * so traversing it from the beginning makes it likely for newly + /* The newly activated connections are added to the end of the list, + * so traversing it from the end makes it likely for newly * activated connections that have no subnet assigned to be served * first. That is a simple yet fair policy, which is good. */ - nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) { + nm_manager_for_each_active_connection_prev (priv->manager, ac, tmp_list) { NMDevice *to_device; to_device = nm_active_connection_get_device(ac); @@ -588,12 +587,6 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) * there was no valid hostname to start with. */ - /* Clear lookup addresses if we have a hostname, so that we don't - * restart the reverse lookup thread later. - */ - if (new_hostname) - g_clear_object(&priv->lookup.addr); - /* Update the DNS only if the hostname is actually * going to change. */ @@ -602,11 +595,14 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) priv->cur_hostname = g_strdup(new_hostname); /* Notify the DNS manager of the hostname change so that the domain part, if - * present, can be added to the search list. + * present, can be added to the search list. Set the @updating_dns flag + * so that dns_config_changed() doesn't try again to restart DNS lookup. */ + priv->updating_dns = TRUE; nm_dns_manager_set_hostname(priv->dns_manager, priv->cur_hostname, all_devices_not_active(self)); + priv->updating_dns = FALSE; } /* Finally, set kernel hostname */ @@ -639,57 +635,176 @@ _set_hostname(NMPolicy *self, const char *new_hostname, const char *msg) g_object_ref(self)); } -static void -lookup_callback(GObject *source, GAsyncResult *result, gpointer user_data) +typedef struct { + NMDevice *device; + int priority; + bool from_dhcp : 1; + bool from_dns : 1; + bool IS_IPv4 : 1; + bool is_default : 1; +} DeviceHostnameInfo; + +static int +device_hostname_info_compare(gconstpointer a, gconstpointer b) { - NMPolicy * self; - NMPolicyPrivate *priv; - gs_free char * hostname = NULL; - gs_free_error GError *error = NULL; + const DeviceHostnameInfo *info1 = a; + const DeviceHostnameInfo *info2 = b; - hostname = g_resolver_lookup_by_address_finish(G_RESOLVER(source), result, &error); - if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return; + NM_CMP_FIELD(info1, info2, priority); + NM_CMP_FIELD_UNSAFE(info2, info1, is_default); - self = user_data; - priv = NM_POLICY_GET_PRIVATE(self); + return 0; +} + +NM_CON_DEFAULT_NOP("hostname.from-dhcp"); +NM_CON_DEFAULT_NOP("hostname.from-dns-lookup"); +NM_CON_DEFAULT_NOP("hostname.only-from-default"); + +static gboolean +device_get_hostname_property_boolean(NMDevice *device, const char *name) +{ + NMSettingHostname *s_hostname; + char buf[128]; + int value; + NMTernary default_value; - g_clear_object(&priv->lookup.cancellable); + nm_assert(NM_IN_STRSET(name, + NM_SETTING_HOSTNAME_FROM_DHCP, + NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP, + NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT)); - if (hostname) - _set_hostname(self, hostname, "from address lookup"); + s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME); + + if (s_hostname) { + g_object_get(s_hostname, name, &value, NULL); + if (NM_IN_SET(value, NM_TERNARY_FALSE, NM_TERNARY_TRUE)) + return value; + } + + if (nm_streq(name, NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT)) + default_value = NM_TERNARY_FALSE; else - _set_hostname(self, NULL, error->message); + default_value = NM_TERNARY_TRUE; + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + nm_sprintf_buf(buf, "hostname.%s", name), + device, + NM_TERNARY_FALSE, + NM_TERNARY_TRUE, + default_value); +} + +static int +device_get_hostname_priority(NMDevice *device) +{ + NMSettingHostname *s_hostname; + int priority; + + s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME); + if (s_hostname) { + priority = nm_setting_hostname_get_priority(s_hostname); + if (priority != 0) + return priority; + } + + return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA, + NM_CON_DEFAULT("hostname.priority"), + device, + G_MININT, + G_MAXINT, + 100); +} + +static GArray * +build_device_hostname_infos(NMPolicy *self) +{ + NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self); + const CList * tmp_clist; + NMActiveConnection *ac; + GArray * array = NULL; + + nm_manager_for_each_active_connection (priv->manager, ac, tmp_clist) { + DeviceHostnameInfo *info; + NMDevice * device; + gboolean only_from_default; + gboolean is_default; + int IS_IPv4; + + device = nm_active_connection_get_device(ac); + if (!device) + continue; + + only_from_default = + device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT); + + for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) { + is_default = (ac == (IS_IPv4 ? priv->default_ac4 : priv->default_ac6)); + if (only_from_default && !is_default) + continue; + + if (!array) + array = g_array_sized_new(FALSE, FALSE, sizeof(DeviceHostnameInfo), 4); + + info = nm_g_array_append_new(array, DeviceHostnameInfo); + *info = (DeviceHostnameInfo){ + .device = device, + .priority = device_get_hostname_priority(device), + .from_dhcp = + device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_FROM_DHCP), + .from_dns = + device_get_hostname_property_boolean(device, + NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP), + .IS_IPv4 = IS_IPv4, + .is_default = is_default, + }; + } + } + + if (array && array->len > 1) { + const DeviceHostnameInfo *info0; + guint i; + + g_array_sort(array, device_hostname_info_compare); + + info0 = &g_array_index(array, DeviceHostnameInfo, 0); + if (info0->priority < 0) { + for (i = 1; i < array->len; i++) { + const DeviceHostnameInfo *info = &g_array_index(array, DeviceHostnameInfo, i); + + if (info->priority > info0->priority) { + g_array_set_size(array, i); + break; + } + } + } + } + + return array; } static void -lookup_by_address(NMPolicy *self) +device_dns_lookup_done(NMDevice *device, gpointer user_data) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMPolicy *self = user_data; - nm_clear_g_cancellable(&priv->lookup.cancellable); - priv->lookup.cancellable = g_cancellable_new(); - g_resolver_lookup_by_address_async(priv->lookup.resolver, - priv->lookup.addr, - priv->lookup.cancellable, - lookup_callback, - self); + g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self); + + update_system_hostname(self, "lookup finished"); } static void update_system_hostname(NMPolicy *self, const char *msg) { - NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self); - const char * configured_hostname; - gs_free char * temp_hostname = NULL; - const char * dhcp_hostname, *p; - NMIP4Config * ip4_config; - NMIP6Config * ip6_config; - gboolean external_hostname = FALSE; - const NMPlatformIP4Address *addr4; - const NMPlatformIP6Address *addr6; - NMDevice * device; - NMDhcpConfig * dhcp_config; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + const char * configured_hostname; + gs_free char * temp_hostname = NULL; + const char * dhcp_hostname, *p; + gboolean external_hostname = FALSE; + NMDhcpConfig * dhcp_config; + gs_unref_array GArray *infos = NULL; + DeviceHostnameInfo * info; + guint i; + int addr_family; g_return_if_fail(self != NULL); @@ -700,8 +815,6 @@ update_system_hostname(NMPolicy *self, const char *msg) _LOGT(LOGD_DNS, "set-hostname: updating hostname (%s)", msg); - nm_clear_g_cancellable(&priv->lookup.cancellable); - /* Check if the hostname was set externally to NM, so that in that case * we can avoid to fallback to the one we got when we started. * Consider "not specific" hostnames as equal. */ @@ -729,10 +842,9 @@ update_system_hostname(NMPolicy *self, const char *msg) /* Hostname precedence order: * * 1) a configured hostname (from settings) - * 2) automatic hostname from the default device's config (DHCP, VPN, etc) - * 3) the last hostname set outside NM - * 4) reverse-DNS of the best device's IPv4 address - * + * 2) automatic hostname from DHCP of eligible interfaces + * 3) reverse-DNS lookup of the first address on eligible interfaces + * 4) the last hostname set outside NM */ /* Try a persistent hostname first */ @@ -743,40 +855,67 @@ update_system_hostname(NMPolicy *self, const char *msg) return; } - if (priv->default_ac4) { - /* Grab a hostname out of the device's DHCP4 config */ - dhcp_config = nm_device_get_dhcp_config(get_default_device(self, AF_INET), AF_INET); - if (dhcp_config) { - dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "host_name"); - if (dhcp_hostname && dhcp_hostname[0]) { - p = nm_str_skip_leading_spaces(dhcp_hostname); - if (p[0]) { - _set_hostname(self, p, "from DHCPv4"); - priv->dhcp_hostname = TRUE; - return; + infos = build_device_hostname_infos(self); + + if (infos && _LOGT_ENABLED(LOGD_DNS)) { + _LOGT(LOGD_DNS, "device hostname info:"); + for (i = 0; i < infos->len; i++) { + info = &g_array_index(infos, DeviceHostnameInfo, i); + _LOGT(LOGD_DNS, + " - prio:%5d ipv%c%s %s %s dev:%s", + info->priority, + info->IS_IPv4 ? '4' : '6', + info->is_default ? " (def)" : " ", + info->from_dhcp ? "dhcp " : " ", + info->from_dns ? "dns " : " ", + nm_device_get_iface(info->device)); + } + } + + for (i = 0; infos && i < infos->len; i++) { + info = &g_array_index(infos, DeviceHostnameInfo, i); + addr_family = info->IS_IPv4 ? AF_INET : AF_INET6; + g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self); + + if (info->from_dhcp) { + dhcp_config = nm_device_get_dhcp_config(info->device, addr_family); + if (dhcp_config) { + dhcp_hostname = + nm_dhcp_config_get_option(dhcp_config, + info->IS_IPv4 ? "host_name" : "fqdn_fqdn"); + if (dhcp_hostname && dhcp_hostname[0]) { + p = nm_str_skip_leading_spaces(dhcp_hostname); + if (p[0]) { + _set_hostname(self, p, info->IS_IPv4 ? "from DHCPv4" : "from DHCPv6"); + priv->dhcp_hostname = TRUE; + return; + } + _LOGW(LOGD_DNS, + "set-hostname: DHCPv%c-provided hostname '%s' looks invalid; " + "ignoring it", + nm_utils_addr_family_to_char(addr_family), + dhcp_hostname); } - _LOGW(LOGD_DNS, - "set-hostname: DHCPv4-provided hostname '%s' looks invalid; ignoring it", - dhcp_hostname); } } - } - if (priv->default_ac6) { - /* Grab a hostname out of the device's DHCP6 config */ - dhcp_config = nm_device_get_dhcp_config(get_default_device(self, AF_INET6), AF_INET6); - if (dhcp_config) { - dhcp_hostname = nm_dhcp_config_get_option(dhcp_config, "fqdn_fqdn"); - if (dhcp_hostname && dhcp_hostname[0]) { - p = nm_str_skip_leading_spaces(dhcp_hostname); - if (p[0]) { - _set_hostname(self, p, "from DHCPv6"); - priv->dhcp_hostname = TRUE; + if (priv->hostname_mode != NM_POLICY_HOSTNAME_MODE_DHCP) { + if (info->from_dns) { + const char *result; + gboolean wait = FALSE; + + result = nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait); + if (result) { + _set_hostname(self, result, "from address lookup"); + return; + } + if (wait) { + g_signal_connect(info->device, + NM_DEVICE_DNS_LOOKUP_DONE, + (GCallback) device_dns_lookup_done, + self); return; } - _LOGW(LOGD_DNS, - "set-hostname: DHCPv6-provided hostname '%s' looks invalid; ignoring it", - dhcp_hostname); } } } @@ -800,14 +939,6 @@ update_system_hostname(NMPolicy *self, const char *msg) priv->dhcp_hostname = FALSE; - if (!priv->default_ac4 && !priv->default_ac6) { - /* No best device; fall back to the last hostname set externally - * to NM or if there wasn't one, 'localhost.localdomain' - */ - _set_hostname(self, priv->orig_hostname, "no default device"); - return; - } - /* If no automatically-configured hostname, try using the last hostname * set externally to NM */ @@ -816,30 +947,7 @@ update_system_hostname(NMPolicy *self, const char *msg) return; } - /* No configured hostname, no automatically determined hostname, and no - * bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address. - */ - device = get_default_device(self, AF_INET); - ip4_config = device ? nm_device_get_ip4_config(device) : NULL; - - device = get_default_device(self, AF_INET6); - ip6_config = device ? nm_device_get_ip6_config(device) : NULL; - - if (ip4_config && (addr4 = nm_ip4_config_get_first_address(ip4_config))) { - g_clear_object(&priv->lookup.addr); - priv->lookup.addr = - g_inet_address_new_from_bytes((guint8 *) &addr4->address, G_SOCKET_FAMILY_IPV4); - } else if (ip6_config && (addr6 = nm_ip6_config_get_first_address(ip6_config))) { - g_clear_object(&priv->lookup.addr); - priv->lookup.addr = - g_inet_address_new_from_bytes((guint8 *) &addr6->address, G_SOCKET_FAMILY_IPV6); - } else { - /* No valid IP config; fall back to localhost.localdomain */ - _set_hostname(self, NULL, "no IP config"); - return; - } - - lookup_by_address(self); + _set_hostname(self, NULL, "no hostname found"); } static void @@ -1433,6 +1541,30 @@ hostname_changed(NMHostnameManager *hostname_manager, GParamSpec *pspec, gpointe update_system_hostname(self, "hostname changed"); } +void +nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self) +{ + NMPolicyPrivate * priv = NM_POLICY_GET_PRIVATE(self); + NMSettingsConnection *const *connections = NULL; + guint i; + + _LOGT(LOGD_DEVICE, "unblocking failed OVS interfaces"); + + connections = nm_settings_get_connections(priv->settings, NULL); + for (i = 0; connections[i]; i++) { + NMSettingsConnection *sett_conn = connections[i]; + NMConnection * connection = nm_settings_connection_get_connection(sett_conn); + + if (nm_connection_get_setting_ovs_interface(connection)) { + nm_settings_connection_autoconnect_retries_reset(sett_conn); + nm_settings_connection_autoconnect_blocked_reason_set( + sett_conn, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED, + FALSE); + } + } +} + static gboolean reset_autoconnect_all( NMPolicy *self, @@ -1801,6 +1933,8 @@ device_state_changed(NMDevice * device, switch (new_state) { case NM_DEVICE_STATE_FAILED: + g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self); + /* Mark the connection invalid if it failed during activation so that * it doesn't get automatically chosen over and over and over again. */ @@ -1939,6 +2073,8 @@ device_state_changed(NMDevice * device, ip6_remove_device_prefix_delegations(self, device); break; case NM_DEVICE_STATE_DISCONNECTED: + g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self); + /* Reset retry counts for a device's connections when carrier on; if cable * was unplugged and plugged in again, we should try to reconnect. */ @@ -2416,33 +2552,19 @@ dns_config_changed(NMDnsManager *dns_manager, gpointer user_data) { NMPolicy * self = (NMPolicy *) user_data; NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self); + NMDevice * device; + const CList * tmp_lst; - /* Restart a thread for reverse-DNS lookup after we are signalled that - * DNS changed. Because the result from a previous run may not be right - * (race in updating DNS and doing the reverse lookup). - */ - - nm_clear_g_cancellable(&priv->lookup.cancellable); - - /* Re-start the hostname lookup thread if we don't have hostname yet. */ - if (priv->lookup.addr) { - char * str = NULL; - gs_free char *hostname = NULL; - - /* Check if the hostname was externally set */ - if ((hostname = _get_hostname(self)) && nm_utils_is_specific_hostname(hostname) - && !nm_streq0(hostname, priv->last_hostname)) { - g_clear_object(&priv->lookup.addr); - return; - } - - _LOGD(LOGD_DNS, - "restarting reverse-lookup thread for address %s", - (str = g_inet_address_to_string(priv->lookup.addr))); - g_free(str); + /* We are currently updating the hostname in the DNS manager. + * This doesn't warrant a new DNS lookup.*/ + if (priv->updating_dns) + return; - lookup_by_address(self); + nm_manager_for_each_device (priv->manager, device, tmp_lst) { + nm_device_clear_dns_lookup_data(device); } + + update_system_hostname(self, "DNS configuration changed"); } static void @@ -2682,8 +2804,6 @@ constructed(GObject *object) G_CALLBACK(dns_config_changed), self); - priv->lookup.resolver = g_resolver_get_default(); - g_signal_connect(priv->hostname_manager, "notify::" NM_HOSTNAME_MANAGER_HOSTNAME, (GCallback) hostname_changed, @@ -2764,10 +2884,6 @@ dispose(GObject *object) NMDevice * device; ActivateData * data, *data_safe; - nm_clear_g_cancellable(&priv->lookup.cancellable); - g_clear_object(&priv->lookup.addr); - g_clear_object(&priv->lookup.resolver); - nm_clear_g_object(&priv->default_ac4); nm_clear_g_object(&priv->default_ac6); nm_clear_g_object(&priv->activating_ac4); diff --git a/src/nm-policy.h b/src/core/nm-policy.h index feac9ef7..fa216db3 100644 --- a/src/nm-policy.h +++ b/src/core/nm-policy.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2004 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. @@ -32,6 +32,8 @@ NMActiveConnection *nm_policy_get_default_ip6_ac(NMPolicy *policy); NMActiveConnection *nm_policy_get_activating_ip4_ac(NMPolicy *policy); NMActiveConnection *nm_policy_get_activating_ip6_ac(NMPolicy *policy); +void nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self); + /** * NMPolicyHostnameMode * @NM_POLICY_HOSTNAME_MODE_NONE: never update the transient hostname. diff --git a/src/nm-proxy-config.c b/src/core/nm-proxy-config.c index 8e8c9030..f41601c9 100644 --- a/src/nm-proxy-config.c +++ b/src/core/nm-proxy-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-proxy-config.h" @@ -148,7 +148,7 @@ nm_proxy_config_init(NMProxyConfig *config) NMProxyConfig * nm_proxy_config_new(void) { - return NM_PROXY_CONFIG(g_object_new(NM_TYPE_PROXY_CONFIG, NULL)); + return g_object_new(NM_TYPE_PROXY_CONFIG, NULL); } static void diff --git a/src/nm-proxy-config.h b/src/core/nm-proxy-config.h index 305e2de6..7aa587d0 100644 --- a/src/nm-proxy-config.h +++ b/src/core/nm-proxy-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Atul Anand <atulhjp@gmail.com>. */ diff --git a/src/nm-rfkill-manager.c b/src/core/nm-rfkill-manager.c index 4b3e18d7..f032851e 100644 --- a/src/nm-rfkill-manager.c +++ b/src/core/nm-rfkill-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-rfkill-manager.h" @@ -367,7 +367,7 @@ nm_rfkill_manager_init(NMRfkillManager *self) for (i = 0; i < RFKILL_TYPE_MAX; i++) priv->rfkill_states[i] = RFKILL_UNBLOCKED; - priv->udev_client = nm_udev_client_new((const char *[]){"rfkill", NULL}, handle_uevent, self); + priv->udev_client = nm_udev_client_new(NM_MAKE_STRV("rfkill"), handle_uevent, self); enumerate = nm_udev_client_enumerate_new(priv->udev_client); udev_enumerate_scan_devices(enumerate); @@ -391,7 +391,7 @@ nm_rfkill_manager_init(NMRfkillManager *self) NMRfkillManager * nm_rfkill_manager_new(void) { - return NM_RFKILL_MANAGER(g_object_new(NM_TYPE_RFKILL_MANAGER, NULL)); + return g_object_new(NM_TYPE_RFKILL_MANAGER, NULL); } static void @@ -405,7 +405,7 @@ dispose(GObject *object) priv->killswitches = NULL; } - priv->udev_client = nm_udev_client_unref(priv->udev_client); + priv->udev_client = nm_udev_client_destroy(priv->udev_client); G_OBJECT_CLASS(nm_rfkill_manager_parent_class)->dispose(object); } diff --git a/src/nm-rfkill-manager.h b/src/core/nm-rfkill-manager.h index a49620bd..d3f66349 100644 --- a/src/nm-rfkill-manager.h +++ b/src/core/nm-rfkill-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2008 Novell, Inc. * Copyright (C) 2007 - 2013 Red Hat, Inc. diff --git a/src/nm-session-monitor.c b/src/core/nm-session-monitor.c index edd89b6b..88de1a00 100644 --- a/src/nm-session-monitor.c +++ b/src/core/nm-session-monitor.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2015 Red Hat, Inc. * Author: David Zeuthen <davidz@redhat.com> @@ -6,7 +6,7 @@ * Author: Matthias Clasen * Author: Pavel Å imerda <psimerda@redhat.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-session-monitor.h" diff --git a/src/nm-session-monitor.h b/src/core/nm-session-monitor.h index e42311d8..63a3136b 100644 --- a/src/nm-session-monitor.h +++ b/src/core/nm-session-monitor.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2010 Red Hat, Inc. * Author: David Zeuthen <davidz@redhat.com> diff --git a/src/nm-sleep-monitor.c b/src/core/nm-sleep-monitor.c index 2a10f92c..ffb4db4e 100644 --- a/src/nm-sleep-monitor.c +++ b/src/core/nm-sleep-monitor.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2016 Red Hat, Inc. * Author: Matthias Clasen <mclasen@redhat.com> */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-sleep-monitor.h" diff --git a/src/nm-sleep-monitor.h b/src/core/nm-sleep-monitor.h index a7c1008d..7d45065b 100644 --- a/src/nm-sleep-monitor.h +++ b/src/core/nm-sleep-monitor.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2016 Red Hat, Inc. * Author: Matthias Clasen <mclasen@redhat.com> diff --git a/src/nm-test-utils-core.h b/src/core/nm-test-utils-core.h index 0c9cfa9e..e655ce22 100644 --- a/src/nm-test-utils-core.h +++ b/src/core/nm-test-utils-core.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ @@ -7,7 +7,7 @@ #define __NM_TEST_UTILS_CORE_H__ #include "NetworkManagerUtils.h" -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #define _NMTST_INSIDE_CORE 1 diff --git a/src/nm-types.h b/src/core/nm-types.h index d24031ea..ab231459 100644 --- a/src/nm-types.h +++ b/src/core/nm-types.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ @@ -77,41 +77,6 @@ typedef enum { NM_ACTIVATION_REASON_USER_REQUEST, } NMActivationReason; -typedef enum { - /* In priority order; higher number == higher priority */ - - NM_IP_CONFIG_SOURCE_UNKNOWN = 0, - - /* for routes, the source is mapped to the uint8 field rtm_protocol. - * Reserve the range [1,0x100] for native RTPROT values. */ - - NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC = 1 + 0, - NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT = 1 + 1, - NM_IP_CONFIG_SOURCE_RTPROT_KERNEL = 1 + 2, - NM_IP_CONFIG_SOURCE_RTPROT_BOOT = 1 + 3, - NM_IP_CONFIG_SOURCE_RTPROT_STATIC = 1 + 4, - NM_IP_CONFIG_SOURCE_RTPROT_RA = 1 + 9, - NM_IP_CONFIG_SOURCE_RTPROT_DHCP = 1 + 16, - _NM_IP_CONFIG_SOURCE_RTPROT_LAST = 1 + 0xFF, - - NM_IP_CONFIG_SOURCE_KERNEL, - NM_IP_CONFIG_SOURCE_SHARED, - NM_IP_CONFIG_SOURCE_IP4LL, - NM_IP_CONFIG_SOURCE_IP6LL, - NM_IP_CONFIG_SOURCE_PPP, - NM_IP_CONFIG_SOURCE_WWAN, - NM_IP_CONFIG_SOURCE_VPN, - NM_IP_CONFIG_SOURCE_DHCP, - NM_IP_CONFIG_SOURCE_NDISC, - NM_IP_CONFIG_SOURCE_USER, -} NMIPConfigSource; - -static inline gboolean -NM_IS_IP_CONFIG_SOURCE_RTPROT(NMIPConfigSource source) -{ - return source > NM_IP_CONFIG_SOURCE_UNKNOWN && source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST; -} - /* platform */ typedef struct _NMPlatform NMPlatform; typedef struct _NMPlatformObject NMPlatformObject; @@ -121,7 +86,6 @@ typedef struct _NMPlatformIP4Route NMPlatformIP4Route; typedef struct _NMPlatformIP6Address NMPlatformIP6Address; typedef struct _NMPlatformIP6Route NMPlatformIP6Route; typedef struct _NMPlatformLink NMPlatformLink; -typedef struct _NMPNetns NMPNetns; typedef struct _NMPObject NMPObject; typedef enum { diff --git a/src/org.freedesktop.NetworkManager.conf b/src/core/org.freedesktop.NetworkManager.conf index 5c2af2e0..5c2af2e0 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/core/org.freedesktop.NetworkManager.conf diff --git a/src/platform/linux/nl802154.h b/src/core/platform/linux/nl802154.h index c21bd079..c21bd079 100644 --- a/src/platform/linux/nl802154.h +++ b/src/core/platform/linux/nl802154.h diff --git a/src/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c index 5bb0b426..81c9f06c 100644 --- a/src/platform/nm-fake-platform.c +++ b/src/core/platform/nm-fake-platform.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-fake-platform.h" @@ -16,7 +16,7 @@ #include "nm-utils.h" #include "nm-core-utils.h" -#include "nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-platform-private.h" #include "nmp-object.h" diff --git a/src/platform/nm-fake-platform.h b/src/core/platform/nm-fake-platform.h index c3ec8921..a1d44f8f 100644 --- a/src/platform/nm-fake-platform.h +++ b/src/core/platform/nm-fake-platform.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/platform/nm-linux-platform.c b/src/core/platform/nm-linux-platform.c index b377c85e..7bd42bba 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/core/platform/nm-linux-platform.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-linux-platform.h" @@ -12,17 +12,20 @@ #include <endian.h> #include <fcntl.h> #include <libudev.h> +#include <net/ethernet.h> #include <linux/fib_rules.h> #include <linux/ip.h> -#include <linux/if_arp.h> +#include <linux/if.h> #include <linux/if_bridge.h> #include <linux/if_link.h> #include <linux/if_tun.h> #include <linux/if_tunnel.h> +#include <linux/if_vlan.h> #include <linux/ip6_tunnel.h> #include <linux/tc_act/tc_mirred.h> #include <netinet/icmp6.h> #include <netinet/in.h> +#include <net/if_arp.h> #include <poll.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -37,11 +40,11 @@ #include "nm-glib-aux/nm-secret-utils.h" #include "nm-glib-aux/nm-c-list.h" -#include "nm-netlink.h" +#include "nm-platform/nm-netlink.h" #include "nm-core-utils.h" #include "nmp-object.h" -#include "nmp-netns.h" -#include "nm-platform-utils.h" +#include "nm-platform/nmp-netns.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-platform-private.h" #include "wifi/nm-wifi-utils.h" #include "wifi/nm-wifi-utils-wext.h" @@ -2786,7 +2789,7 @@ toobig_allowedips: if (nest_curr_allowed_ip) nla_nest_cancel(msg, nest_curr_allowed_ip); if (nest_allowed_ips) - nla_nest_cancel(msg, nest_allowed_ips); + _nla_nest_end(msg, nest_allowed_ips); _nla_nest_end(msg, nest_curr_peer); _nla_nest_end(msg, nest_peers); goto send; @@ -7650,7 +7653,7 @@ static void link_set_sriov_params_async(NMPlatform * platform, int ifindex, guint num_vfs, - NMTernary autoprobe, + NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer data, GCancellable * cancellable) @@ -7723,10 +7726,11 @@ link_set_sriov_params_async(NMPlatform * platform, } if (current_num == num_vfs - && (autoprobe == NM_TERNARY_DEFAULT || current_autoprobe == autoprobe)) + && (autoprobe == NM_OPTION_BOOL_DEFAULT || current_autoprobe == autoprobe)) goto out_idle; - if (NM_IN_SET(autoprobe, NM_TERNARY_TRUE, NM_TERNARY_FALSE) && current_autoprobe != autoprobe + if (NM_IN_SET(autoprobe, NM_OPTION_BOOL_TRUE, NM_OPTION_BOOL_FALSE) + && current_autoprobe != autoprobe && !nm_platform_sysctl_set( NM_PLATFORM_GET, NMP_SYSCTL_PATHID_NETDIR(dirfd, ifname, "device/sriov_drivers_autoprobe"), @@ -8281,13 +8285,6 @@ wifi_get_capabilities(NMPlatform *platform, int ifindex, NMDeviceWifiCapabilitie return TRUE; } -static gboolean -wifi_get_bssid(NMPlatform *platform, int ifindex, guint8 *bssid) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_bssid(wifi_data, bssid); -} - static guint32 wifi_get_frequency(NMPlatform *platform, int ifindex) { @@ -8296,17 +8293,14 @@ wifi_get_frequency(NMPlatform *platform, int ifindex) } static gboolean -wifi_get_quality(NMPlatform *platform, int ifindex) +wifi_get_station(NMPlatform * platform, + int ifindex, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate) { WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_qual(wifi_data); -} - -static guint32 -wifi_get_rate(NMPlatform *platform, int ifindex) -{ - WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE); - return nm_wifi_utils_get_rate(wifi_data); + return nm_wifi_utils_get_station(wifi_data, out_bssid, out_quality, out_rate); } static NM80211Mode @@ -8641,16 +8635,9 @@ ip_route_add(NMPlatform * platform, nm_auto_nlmsg struct nl_msg *nlmsg = NULL; NMPObject obj; - switch (addr_family) { - case AF_INET: - nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP4_ROUTE, (const NMPlatformObject *) route); - break; - case AF_INET6: - nmp_object_stackinit(&obj, NMP_OBJECT_TYPE_IP6_ROUTE, (const NMPlatformObject *) route); - break; - default: - nm_assert_not_reached(); - } + nmp_object_stackinit(&obj, + NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), + (const NMPlatformObject *) route); nm_platform_ip_route_normalize(addr_family, NMP_OBJECT_CAST_IP_ROUTE(&obj)); @@ -9606,7 +9593,7 @@ finalize(GObject *object) g_hash_table_destroy(priv->sysctl_get_prev_values); } - priv->udev_client = nm_udev_client_unref(priv->udev_client); + priv->udev_client = nm_udev_client_destroy(priv->udev_client); G_OBJECT_CLASS(nm_linux_platform_parent_class)->finalize(object); } @@ -9669,10 +9656,8 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass) platform_class->infiniband_partition_delete = infiniband_partition_delete; platform_class->wifi_get_capabilities = wifi_get_capabilities; - platform_class->wifi_get_bssid = wifi_get_bssid; platform_class->wifi_get_frequency = wifi_get_frequency; - platform_class->wifi_get_quality = wifi_get_quality; - platform_class->wifi_get_rate = wifi_get_rate; + platform_class->wifi_get_station = wifi_get_station; platform_class->wifi_get_mode = wifi_get_mode; platform_class->wifi_set_mode = wifi_set_mode; platform_class->wifi_set_powersave = wifi_set_powersave; diff --git a/src/platform/nm-linux-platform.h b/src/core/platform/nm-linux-platform.h index 98935b98..6837e64a 100644 --- a/src/platform/nm-linux-platform.h +++ b/src/core/platform/nm-linux-platform.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 Red Hat, Inc. */ diff --git a/src/platform/nm-platform-private.h b/src/core/platform/nm-platform-private.h index d99e330b..cf805689 100644 --- a/src/platform/nm-platform-private.h +++ b/src/core/platform/nm-platform-private.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2017 Red Hat, Inc. */ diff --git a/src/platform/nm-platform.c b/src/core/platform/nm-platform.c index 7969206c..0e5f8ab5 100644 --- a/src/platform/nm-platform.c +++ b/src/core/platform/nm-platform.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2012 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-platform.h" @@ -29,10 +29,10 @@ #include "nm-glib-aux/nm-secret-utils.h" #include "nm-core-utils.h" -#include "nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-platform-private.h" #include "nmp-object.h" -#include "nmp-netns.h" +#include "nm-platform/nmp-netns.h" /*****************************************************************************/ @@ -1842,7 +1842,7 @@ nm_platform_link_supports_sriov(NMPlatform *self, int ifindex) * @ifindex: the index of the interface to change * @num_vfs: the number of VFs to create * @autoprobe: the new autoprobe-drivers value (pass - * %NM_TERNARY_DEFAULT to keep current value) + * %NM_OPTION_BOOL_DEFAULT to keep current value) * @callback: called when the operation finishes * @callback_data: data passed to @callback * @cancellable: cancellable to abort the operation @@ -1855,7 +1855,7 @@ void nm_platform_link_set_sriov_params_async(NMPlatform * self, int ifindex, guint num_vfs, - NMTernary autoprobe, + NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable * cancellable) @@ -3051,16 +3051,6 @@ nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCap return klass->wifi_get_capabilities(self, ifindex, caps); } -gboolean -nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid) -{ - _CHECK_SELF(self, klass, FALSE); - - g_return_val_if_fail(ifindex > 0, FALSE); - - return klass->wifi_get_bssid(self, ifindex, bssid); -} - guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) { @@ -3071,24 +3061,18 @@ nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex) return klass->wifi_get_frequency(self, ifindex); } -int -nm_platform_wifi_get_quality(NMPlatform *self, int ifindex) -{ - _CHECK_SELF(self, klass, 0); - - g_return_val_if_fail(ifindex > 0, 0); - - return klass->wifi_get_quality(self, ifindex); -} - -guint32 -nm_platform_wifi_get_rate(NMPlatform *self, int ifindex) +gboolean +nm_platform_wifi_get_station(NMPlatform * self, + int ifindex, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate) { - _CHECK_SELF(self, klass, 0); + _CHECK_SELF(self, klass, FALSE); - g_return_val_if_fail(ifindex > 0, 0); + g_return_val_if_fail(ifindex > 0, FALSE); - return klass->wifi_get_rate(self, ifindex); + return klass->wifi_get_station(self, ifindex, out_bssid, out_quality, out_rate); } NM80211Mode @@ -3298,10 +3282,10 @@ _to_string_ifa_flags(guint32 ifa_flags, char *buf, gsize size) /*****************************************************************************/ gboolean -nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, - int ifindex, - NMSettingWiredWakeOnLan wol, - const char * wol_password) +nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, + int ifindex, + _NMSettingWiredWakeOnLan wol, + const char * wol_password) { _CHECK_SELF_NETNS(self, klass, netns, FALSE); @@ -3338,13 +3322,6 @@ nm_platform_ethtool_get_link_settings(NMPlatform * self, return nmp_utils_ethtool_get_link_settings(ifindex, out_autoneg, out_speed, out_duplex); } -NM_UTILS_LOOKUP_STR_DEFINE(nm_platform_link_duplex_type_to_string, - NMPlatformLinkDuplexType, - NM_UTILS_LOOKUP_DEFAULT_WARN(NULL), - NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"), - NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_FULL, "full"), - NM_UTILS_LOOKUP_STR_ITEM(NM_PLATFORM_LINK_DUPLEX_HALF, "half"), ); - /*****************************************************************************/ NMEthtoolFeatureStates * @@ -3362,8 +3339,8 @@ nm_platform_ethtool_set_features( NMPlatform * self, int ifindex, const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */) + const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */) { _CHECK_SELF_NETNS(self, klass, netns, FALSE); @@ -3746,7 +3723,7 @@ _addr_array_clean_expired(int addr_family, } #endif - if (addr_family == AF_INET6 && NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TEMPORARY)) { + if (!NM_IS_IPv4(addr_family) && NM_FLAGS_HAS(a->n_ifa_flags, IFA_F_TEMPORARY)) { /* temporary addresses are never added explicitly by NetworkManager but * kernel adds them via mngtempaddr flag. * @@ -3987,7 +3964,7 @@ nm_platform_ip_address_sync(NMPlatform *self, GPtrArray * addresses_prune) { const gint32 now = nm_utils_get_monotonic_timestamp_sec(); - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); gs_unref_hashtable GHashTable *known_addresses_idx = NULL; GPtrArray * plat_addresses; GHashTable * known_subnets = NULL; @@ -4336,7 +4313,7 @@ nm_platform_ip_address_get_prune_list(NMPlatform *self, int ifindex, gboolean exclude_ipv6_temporary_addrs) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMDedupMultiHeadEntry *head_entry; NMPLookup lookup; GPtrArray * result; @@ -4388,10 +4365,7 @@ nm_platform_ip_route_get_prune_list(NMPlatform * self, NM_IP_ROUTE_TABLE_SYNC_MODE_FULL, NM_IP_ROUTE_TABLE_SYNC_MODE_ALL)); - nmp_lookup_init_object(&lookup, - addr_family == AF_INET ? NMP_OBJECT_TYPE_IP4_ROUTE - : NMP_OBJECT_TYPE_IP6_ROUTE, - ifindex); + nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)), ifindex); head_entry = nm_platform_lookup(self, &lookup); if (!head_entry) return NULL; @@ -4447,6 +4421,7 @@ nm_platform_ip_route_sync(NMPlatform *self, GPtrArray * routes_prune, GPtrArray **out_temporary_not_available) { + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPlatformVTableRoute *vt; gs_unref_hashtable GHashTable *routes_idx = NULL; const NMPObject * conf_o; @@ -4456,10 +4431,8 @@ nm_platform_ip_route_sync(NMPlatform *self, gboolean success = TRUE; char sbuf1[sizeof(_nm_utils_to_string_buffer)]; char sbuf2[sizeof(_nm_utils_to_string_buffer)]; - const gboolean IS_IPv4 = (addr_family == AF_INET); nm_assert(NM_IS_PLATFORM(self)); - nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); nm_assert(ifindex > 0); vt = &nm_platform_vtable_route.vx[IS_IPv4]; @@ -4671,9 +4644,9 @@ sync_route_add: prune_o = routes_prune->pdata[i]; - nm_assert((addr_family == AF_INET + nm_assert((NM_IS_IPv4(addr_family) && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP4_ROUTE) - || (addr_family == AF_INET6 + || (!NM_IS_IPv4(addr_family) && NMP_OBJECT_GET_TYPE(prune_o) == NMP_OBJECT_TYPE_IP6_ROUTE)); if (routes_idx && g_hash_table_lookup(routes_idx, prune_o)) @@ -4816,8 +4789,8 @@ _ip_route_add(NMPlatform *self, NMPNlmFlags flags, int addr_family, gconstpointe _LOG3D("route: %-10s IPv%c route: %s", _nmp_nlm_flag_to_string(flags & NMP_NLM_FLAG_FMASK), nm_utils_addr_family_to_char(addr_family), - addr_family == AF_INET ? nm_platform_ip4_route_to_string(route, sbuf, sizeof(sbuf)) - : nm_platform_ip6_route_to_string(route, sbuf, sizeof(sbuf))); + NM_IS_IPv4(addr_family) ? nm_platform_ip4_route_to_string(route, sbuf, sizeof(sbuf)) + : nm_platform_ip6_route_to_string(route, sbuf, sizeof(sbuf))); return klass->ip_route_add(self, flags, addr_family, route); } @@ -5647,7 +5620,7 @@ nm_platform_lnk_bridge_to_string(const NMPlatformLnkBridge *lnk, char *buf, gsiz lnk->vlan_protocol, (int) lnk->vlan_stats_enabled, lnk->group_fwd_mask, - NM_ETHER_ADDR_FORMAT_VAL(lnk->group_addr), + NM_ETHER_ADDR_FORMAT_VAL(&lnk->group_addr), (int) lnk->mcast_snooping, lnk->mcast_router, (int) lnk->mcast_query_use_ifaddr, @@ -6272,11 +6245,16 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf "%s" /* label */ " src %s" "%s" /* external */ + "%s" /* ip4acd_not_ready */ "", s_address, address->plen, - broadcast_address ? " brd " : "", - broadcast_address ? _nm_utils_inet4_ntop(broadcast_address, str_broadcast) : "", + broadcast_address != 0u || address->use_ip4_broadcast_address + ? (address->use_ip4_broadcast_address ? " brd " : " brd* ") + : "", + broadcast_address != 0u || address->use_ip4_broadcast_address + ? _nm_utils_inet4_ntop(broadcast_address, str_broadcast) + : "", str_lft_p, str_pref_p, str_time_p, @@ -6285,7 +6263,8 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf _to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)), str_label, nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)), - address->external ? " ext" : ""); + address->external ? " ext" : "", + address->ip4acd_not_ready ? " ip4acd-not-ready" : ""); g_free(str_peer); return buf; } @@ -6515,7 +6494,9 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz route->plen, s_gateway, str_dev, - route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric), + route->metric_any + ? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??") + : nm_sprintf_buf(str_metric, "%u", route->metric), route->mss, nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), _rtm_flags_to_string_full(str_rtm_flags, sizeof(str_rtm_flags), route->r_rtm_flags), @@ -6639,7 +6620,9 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz route->plen, s_gateway, str_dev, - route->metric_any ? "??" : nm_sprintf_buf(str_metric, "%u", route->metric), + route->metric_any + ? (route->metric ? nm_sprintf_buf(str_metric, "??+%u", route->metric) : "??") + : nm_sprintf_buf(str_metric, "%u", route->metric), route->mss, nmp_utils_ip_config_source_to_string(route->rt_source, s_source, sizeof(s_source)), route->src_plen || !IN6_IS_ADDR_UNSPECIFIED(&route->src) @@ -7841,7 +7824,7 @@ nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState nm_hash_update_vals(h, obj->ifindex, obj->addr_source, - nm_platform_ip4_broadcast_address_from_addr(obj), + obj->use_ip4_broadcast_address ? obj->broadcast_address : ((in_addr_t) 0u), obj->timestamp, obj->lifetime, obj->preferred, @@ -7849,7 +7832,10 @@ nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState obj->plen, obj->address, obj->peer_address, - NM_HASH_COMBINE_BOOLS(guint8, obj->external)); + NM_HASH_COMBINE_BOOLS(guint8, + obj->external, + obj->use_ip4_broadcast_address, + obj->ip4acd_not_ready)); nm_hash_update_strarr(h, obj->label); } @@ -7861,8 +7847,9 @@ nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Ad NM_CMP_FIELD(a, b, address); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD(a, b, peer_address); - NM_CMP_DIRECT(nm_platform_ip4_broadcast_address_from_addr(a), - nm_platform_ip4_broadcast_address_from_addr(b)); + NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address); + if (a->use_ip4_broadcast_address) + NM_CMP_FIELD(a, b, broadcast_address); NM_CMP_FIELD(a, b, addr_source); NM_CMP_FIELD(a, b, timestamp); NM_CMP_FIELD(a, b, lifetime); @@ -7870,6 +7857,7 @@ nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Ad NM_CMP_FIELD(a, b, n_ifa_flags); NM_CMP_FIELD_STR(a, b, label); NM_CMP_FIELD_UNSAFE(a, b, external); + NM_CMP_FIELD_UNSAFE(a, b, ip4acd_not_ready); return 0; } @@ -7922,7 +7910,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), obj->plen, - nm_platform_ip4_route_get_effective_metric(obj), + obj->metric, obj->tos, NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); break; @@ -7933,7 +7921,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), obj->plen, - nm_platform_ip4_route_get_effective_metric(obj), + obj->metric, obj->tos, /* on top of WEAK_ID: */ obj->ifindex, @@ -7965,7 +7953,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, obj->ifindex, nm_utils_ip4_address_clear_host_address(obj->network, obj->plen), obj->plen, - nm_platform_ip4_route_get_effective_metric(obj), + obj->metric, obj->gateway, nmp_utils_ip_config_source_round_trip_rtprot(obj->rt_source), _ip_route_scope_inv_get_normalized(obj), @@ -7994,7 +7982,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj, obj->ifindex, obj->network, obj->plen, - nm_platform_ip4_route_get_effective_metric(obj), + obj->metric, obj->gateway, obj->rt_source, obj->scope_inv, @@ -8034,8 +8022,7 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->network, b->network, MIN(a->plen, b->plen)); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); - if (!a->metric_any) - NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, metric); NM_CMP_FIELD(a, b, tos); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { NM_CMP_FIELD(a, b, ifindex); @@ -8076,8 +8063,7 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a, NM_CMP_FIELD(a, b, network); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); - if (!a->metric_any) - NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, metric); NM_CMP_FIELD(a, b, gateway); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { NM_CMP_DIRECT(nmp_utils_ip_config_source_round_trip_rtprot(a->rt_source), @@ -8125,7 +8111,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), obj->plen, - nm_platform_ip6_route_get_effective_metric(obj), + obj->metric, *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), obj->src_plen, NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any)); @@ -8137,7 +8123,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, nm_platform_ip_route_get_effective_table(NM_PLATFORM_IP_ROUTE_CAST(obj)), *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), obj->plen, - nm_platform_ip6_route_get_effective_metric(obj), + obj->metric, *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), obj->src_plen, NM_HASH_COMBINE_BOOLS(guint8, obj->metric_any, obj->table_any), @@ -8153,7 +8139,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, obj->ifindex, *nm_utils_ip6_address_clear_host_address(&a1, &obj->network, obj->plen), obj->plen, - nm_platform_ip6_route_get_effective_metric(obj), + obj->metric, obj->gateway, obj->pref_src, *nm_utils_ip6_address_clear_host_address(&a2, &obj->src, obj->src_plen), @@ -8182,7 +8168,7 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj, obj->table_coerced, obj->ifindex, obj->network, - nm_platform_ip6_route_get_effective_metric(obj), + obj->metric, obj->gateway, obj->pref_src, obj->src, @@ -8223,8 +8209,7 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->network, &b->network, MIN(a->plen, b->plen)); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); - if (!a->metric_any) - NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, metric); NM_CMP_DIRECT_IN6ADDR_SAME_PREFIX(&a->src, &b->src, MIN(a->src_plen, b->src_plen)); NM_CMP_FIELD(a, b, src_plen); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID) { @@ -8249,8 +8234,7 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a, NM_CMP_FIELD_IN6ADDR(a, b, network); NM_CMP_FIELD(a, b, plen); NM_CMP_FIELD_UNSAFE(a, b, metric_any); - if (!a->metric_any) - NM_CMP_FIELD(a, b, metric); + NM_CMP_FIELD(a, b, metric); NM_CMP_FIELD_IN6ADDR(a, b, gateway); NM_CMP_FIELD_IN6ADDR(a, b, pref_src); if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_SEMANTICALLY) { diff --git a/src/platform/nm-platform.h b/src/core/platform/nm-platform.h index a1314000..d400c568 100644 --- a/src/platform/nm-platform.h +++ b/src/core/platform/nm-platform.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2018 Red Hat, Inc. */ @@ -9,6 +9,9 @@ #include "nm-dbus-interface.h" #include "nm-core-types-internal.h" +#include "nm-platform/nmp-base.h" +#include "nm-base/nm-base.h" + #include "nm-core-utils.h" #include "nm-setting-vlan.h" #include "nm-setting-wired.h" @@ -322,10 +325,15 @@ typedef enum { guint8 plen; \ \ /* FIXME(l3cfg): the external marker won't be necessary anymore, because we only - * merge addresses we care about, and ignore (don't remove) external addresses. */ \ + * merge addresses we care about, and ignore (don't remove) external addresses. */ \ bool external : 1; \ \ bool use_ip4_broadcast_address : 1; \ + \ + /* Whether the address is ready to be configured. By default, an address is, but this + * flag may indicate that the address is just for tracking purpose only, but the ACD + * state is not yet ready for the address to be configured. */ \ + bool ip4acd_not_ready : 1; \ ; /** @@ -410,9 +418,9 @@ typedef union { * configures addresses. */ #define NM_PLATFORM_ROUTE_METRIC_IP4_DEVICE_ROUTE ((guint32) 0u) -#define __NMPlatformIPRoute_COMMON \ - __NMPlatformObjWithIfindex_COMMON; \ - \ +#define __NMPlatformIPRoute_COMMON \ + __NMPlatformObjWithIfindex_COMMON; \ + \ /* The NMIPConfigSource. For routes that we receive from cache this corresponds * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values). * When adding a route, the source will be coerced to the protocol using @@ -424,11 +432,11 @@ typedef union { * * When deleting an IPv4/IPv6 route, the rtm_protocol field must match (even * if it is not part of the primary key for IPv6) -- unless rtm_protocol is set - * to zero, in which case the first matching route (with proto ignored) is deleted. */ \ - NMIPConfigSource rt_source; \ - \ - guint8 plen; \ - \ + * to zero, in which case the first matching route (with proto ignored) is deleted. */ \ + NMIPConfigSource rt_source; \ + \ + guint8 plen; \ + \ /* RTA_METRICS: * * For IPv4 routes, these properties are part of their @@ -439,24 +447,29 @@ typedef union { * * When deleting a route, kernel seems to ignore the RTA_METRICS properties. * That is a problem/bug for IPv4 because you cannot explicitly select which - * route to delete. Kernel just picks the first. See rh#1475642. */ \ - \ - /* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \ - bool lock_window : 1; \ - bool lock_cwnd : 1; \ - bool lock_initcwnd : 1; \ - bool lock_initrwnd : 1; \ - bool lock_mtu : 1; \ - \ - /* if TRUE, the "metric" field gets ignored and can be overridden with settings from - * the device. This is to track routes that should be configured (e.g. from a DHCP - * lease), but where the actual metric is determined by NMDevice. */ \ - bool metric_any : 1; \ - \ + * route to delete. Kernel just picks the first. See rh#1475642. */ \ + \ + /* RTA_METRICS.RTAX_LOCK (iproute2: "lock" arguments) */ \ + bool lock_window : 1; \ + bool lock_cwnd : 1; \ + bool lock_initcwnd : 1; \ + bool lock_initrwnd : 1; \ + bool lock_mtu : 1; \ + \ + /* if TRUE, the "metric" field is interpreted as an offset that is added to a default + * metric. For example, form a DHCP lease we don't know the actually used metric, because + * that is determined by upper layers (the configuration). However, we have a default + * metric that should be used. So we set "metric_any" to %TRUE, which means to use + * the default metric. However, we still treat the "metric" field as an offset that + * will be added to the default metric. In most case, you want that "metric" is zero + * when setting "metric_any". */ \ + bool metric_any : 1; \ + \ /* like "metric_any", the table is determined by other layers of the code. - * This field overrides "table_coerced" field. */ \ - bool table_any : 1; \ - \ + * This field overrides "table_coerced" field. If "table_any" is true, then + * the "table_coerced" field is ignored (unlike for the metric). */ \ + bool table_any : 1; \ + \ /* rtnh_flags * * Routes with rtm_flags RTM_F_CLONED are hidden by platform and @@ -466,44 +479,46 @@ typedef union { * NOTE: currently we ignore all flags except RTM_F_CLONED * and RTNH_F_ONLINK. * We also may not properly consider the flags as part of the ID - * in route-cmp. */ \ - unsigned r_rtm_flags; \ - \ - /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ - guint32 mss; \ - \ - /* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \ - guint32 window; \ - \ - /* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \ - guint32 cwnd; \ - \ - /* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \ - guint32 initcwnd; \ - \ - /* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \ - guint32 initrwnd; \ - \ - /* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \ - guint32 mtu; \ - \ - /* RTA_PRIORITY (iproute2: metric) */ \ - guint32 metric; \ - \ + * in route-cmp. */ \ + unsigned r_rtm_flags; \ + \ + /* RTA_METRICS.RTAX_ADVMSS (iproute2: advmss) */ \ + guint32 mss; \ + \ + /* RTA_METRICS.RTAX_WINDOW (iproute2: window) */ \ + guint32 window; \ + \ + /* RTA_METRICS.RTAX_CWND (iproute2: cwnd) */ \ + guint32 cwnd; \ + \ + /* RTA_METRICS.RTAX_INITCWND (iproute2: initcwnd) */ \ + guint32 initcwnd; \ + \ + /* RTA_METRICS.RTAX_INITRWND (iproute2: initrwnd) */ \ + guint32 initrwnd; \ + \ + /* RTA_METRICS.RTAX_MTU (iproute2: mtu) */ \ + guint32 mtu; \ + \ + /* RTA_PRIORITY (iproute2: metric) + * If "metric_any" is %TRUE, then this is interpreted as an offset that will be + * added to a default base metric. In such cases, the offset is usually zero. */ \ + guint32 metric; \ + \ /* rtm_table, RTA_TABLE. * * This is not the original table ID. Instead, 254 (RT_TABLE_MAIN) and * zero (RT_TABLE_UNSPEC) are swapped, so that the default is the main - * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \ - guint32 table_coerced; \ - \ + * table. Use nm_platform_route_table_coerce()/nm_platform_route_table_uncoerce(). */ \ + guint32 table_coerced; \ + \ /* rtm_type. * * This is not the original type, if type_coerced is 0 then * it means RTN_UNSPEC otherwise the type value is preserved. - * */ \ - guint8 type_coerced; \ - \ + * */ \ + guint8 type_coerced; \ + \ /*end*/ typedef struct { @@ -964,12 +979,6 @@ typedef struct { } NMPlatformLnkWireGuard; typedef enum { - NM_PLATFORM_LINK_DUPLEX_UNKNOWN, - NM_PLATFORM_LINK_DUPLEX_HALF, - NM_PLATFORM_LINK_DUPLEX_FULL, -} NMPlatformLinkDuplexType; - -typedef enum { NM_PLATFORM_WIREGUARD_CHANGE_FLAG_NONE = 0, NM_PLATFORM_WIREGUARD_CHANGE_FLAG_REPLACE_PEERS = (1LL << 0), NM_PLATFORM_WIREGUARD_CHANGE_FLAG_HAS_PRIVATE_KEY = (1LL << 1), @@ -1026,7 +1035,7 @@ _nm_platform_kernel_support_detected(NMPlatformKernelSupportType type) return G_LIKELY(g_atomic_int_get(&_nm_platform_kernel_support_state[type]) != 0); } -static inline NMTernary +static inline NMOptionBool nm_platform_kernel_support_get_full(NMPlatformKernelSupportType type, gboolean init_if_not_set) { int v; @@ -1036,7 +1045,7 @@ nm_platform_kernel_support_get_full(NMPlatformKernelSupportType type, gboolean i v = g_atomic_int_get(&_nm_platform_kernel_support_state[type]); if (G_UNLIKELY(v == 0)) { if (!init_if_not_set) - return NM_TERNARY_DEFAULT; + return NM_OPTION_BOOL_DEFAULT; v = _nm_platform_kernel_support_init(type, 0); } return (v >= 0); @@ -1045,7 +1054,7 @@ nm_platform_kernel_support_get_full(NMPlatformKernelSupportType type, gboolean i static inline gboolean nm_platform_kernel_support_get(NMPlatformKernelSupportType type) { - return nm_platform_kernel_support_get_full(type, TRUE) != NM_TERNARY_FALSE; + return nm_platform_kernel_support_get_full(type, TRUE) != NM_OPTION_BOOL_FALSE; } /*****************************************************************************/ @@ -1109,7 +1118,7 @@ typedef struct { void (*link_set_sriov_params_async)(NMPlatform * self, int ifindex, guint num_vfs, - int autoprobe, + NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable * cancellable); @@ -1170,6 +1179,11 @@ typedef struct { gboolean (*wifi_get_capabilities)(NMPlatform * self, int ifindex, NMDeviceWifiCapabilities *caps); + gboolean (*wifi_get_station)(NMPlatform * self, + int ifindex, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate); gboolean (*wifi_get_bssid)(NMPlatform *self, int ifindex, guint8 *bssid); guint32 (*wifi_get_frequency)(NMPlatform *self, int ifindex); int (*wifi_get_quality)(NMPlatform *self, int ifindex); @@ -1839,7 +1853,7 @@ gboolean nm_platform_link_set_name(NMPlatform *self, int ifindex, const char *na void nm_platform_link_set_sriov_params_async(NMPlatform * self, int ifindex, guint num_vfs, - int autoprobe, + NMOptionBool autoprobe, NMPlatformAsyncCallback callback, gpointer callback_data, GCancellable * cancellable); @@ -1950,10 +1964,12 @@ gboolean nm_platform_link_tun_get_properties(NMPlatform * self, gboolean nm_platform_wifi_get_capabilities(NMPlatform *self, int ifindex, NMDeviceWifiCapabilities *caps); -gboolean nm_platform_wifi_get_bssid(NMPlatform *self, int ifindex, guint8 *bssid); guint32 nm_platform_wifi_get_frequency(NMPlatform *self, int ifindex); -int nm_platform_wifi_get_quality(NMPlatform *self, int ifindex); -guint32 nm_platform_wifi_get_rate(NMPlatform *self, int ifindex); +gboolean nm_platform_wifi_get_station(NMPlatform * self, + int ifindex, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate); NM80211Mode nm_platform_wifi_get_mode(NMPlatform *self, int ifindex); void nm_platform_wifi_set_mode(NMPlatform *self, int ifindex, NM80211Mode mode); void nm_platform_wifi_set_powersave(NMPlatform *self, int ifindex, guint32 powersave); @@ -2097,18 +2113,18 @@ static inline guint32 nm_platform_ip4_route_get_effective_metric(const NMPlatformIP4Route *r) { nm_assert(r); - nm_assert(!r->metric_any || r->metric == 0); - return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4 : r->metric; + return r->metric_any ? nm_add_clamped_u32(NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, r->metric) + : r->metric; } static inline guint32 nm_platform_ip6_route_get_effective_metric(const NMPlatformIP6Route *r) { nm_assert(r); - nm_assert(!r->metric_any || r->metric == 0); - return r->metric_any ? NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6 : r->metric; + return r->metric_any ? nm_add_clamped_u32(NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, r->metric) + : r->metric; } static inline guint32 @@ -2306,10 +2322,10 @@ const char *nm_platform_route_scope2str(int scope, char *buf, gsize len); int nm_platform_ip_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b); -gboolean nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, - int ifindex, - NMSettingWiredWakeOnLan wol, - const char * wol_password); +gboolean nm_platform_ethtool_set_wake_on_lan(NMPlatform * self, + int ifindex, + _NMSettingWiredWakeOnLan wol, + const char * wol_password); gboolean nm_platform_ethtool_set_link_settings(NMPlatform * self, int ifindex, gboolean autoneg, @@ -2321,17 +2337,13 @@ gboolean nm_platform_ethtool_get_link_settings(NMPlatform * self, guint32 * out_speed, NMPlatformLinkDuplexType *out_duplex); -typedef struct _NMEthtoolFeatureStates NMEthtoolFeatureStates; - NMEthtoolFeatureStates *nm_platform_ethtool_get_link_features(NMPlatform *self, int ifindex); gboolean nm_platform_ethtool_set_features( NMPlatform * self, int ifindex, const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */); - -typedef struct _NMEthtoolCoalesceState NMEthtoolCoalesceState; + const NMOptionBool *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, + gboolean do_set /* or reset */); gboolean nm_platform_ethtool_get_link_coalesce(NMPlatform * self, int ifindex, @@ -2341,15 +2353,11 @@ gboolean nm_platform_ethtool_set_coalesce(NMPlatform * self, int ifindex, const NMEthtoolCoalesceState *coalesce); -typedef struct _NMEthtoolRingState NMEthtoolRingState; - gboolean nm_platform_ethtool_get_link_ring(NMPlatform *self, int ifindex, NMEthtoolRingState *ring); gboolean nm_platform_ethtool_set_ring(NMPlatform *self, int ifindex, const NMEthtoolRingState *ring); -const char *nm_platform_link_duplex_type_to_string(NMPlatformLinkDuplexType duplex); - void nm_platform_ip4_dev_route_blacklist_set(NMPlatform *self, int ifindex, GPtrArray * ip4_dev_route_blacklist); diff --git a/src/platform/nmp-object.c b/src/core/platform/nmp-object.c index 6eea732f..6a26595e 100644 --- a/src/platform/nmp-object.c +++ b/src/core/platform/nmp-object.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nmp-object.h" @@ -16,7 +16,7 @@ #include "nm-glib-aux/nm-secret-utils.h" #include "nm-core-utils.h" -#include "nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "wifi/nm-wifi-utils.h" #include "wpan/nm-wpan-utils.h" @@ -1098,7 +1098,7 @@ _vt_cmd_obj_to_string_lnk_wireguard(const NMPObject * obj, g_snprintf(buf, buf_len, __VA_ARGS__); \ return buf; \ } \ - struct _dummy_struct_for_tailing_semicolon + _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON _vt_cmd_plobj_to_string_id(link, NMPlatformLink, "%d", obj->ifindex); @@ -1390,7 +1390,7 @@ _vt_cmd_obj_copy_lnk_wireguard(NMPObject *dst, const NMPObject *src) cmd \ } \ } \ - struct _dummy_struct_for_tailing_semicolon + _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON _vt_cmd_plobj_id_copy(link, NMPlatformLink, { dst->ifindex = src->ifindex; }); @@ -1485,7 +1485,7 @@ nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2) } \ return 0; \ } \ - struct _dummy_struct_for_tailing_semicolon + _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON _vt_cmd_plobj_id_cmp(link, NMPlatformLink, { NM_CMP_FIELD(obj1, obj2, ifindex); }); @@ -1581,7 +1581,7 @@ nmp_object_id_hash(const NMPObject *obj) cmd; \ } \ } \ - struct _dummy_struct_for_tailing_semicolon + _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON _vt_cmd_plobj_id_hash_update(link, NMPlatformLink, { nm_hash_update_val(h, obj->ifindex); }); diff --git a/src/platform/nmp-object.h b/src/core/platform/nmp-object.h index 58f54dbe..dc2cc86b 100644 --- a/src/platform/nmp-object.h +++ b/src/core/platform/nmp-object.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ @@ -1077,52 +1077,64 @@ nm_platform_dedup_multi_iter_next_obj(NMDedupMultiIter *ipconf_iter, return has_next; } -static inline gboolean -nm_platform_dedup_multi_iter_next_ip4_address(NMDedupMultiIter * ipconf_iter, - const NMPlatformIP4Address **out_address) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(ipconf_iter); - if (out_address) - *out_address = has_next ? NMP_OBJECT_CAST_IP4_ADDRESS(ipconf_iter->current->obj) : NULL; - return has_next; -} - -static inline gboolean -nm_platform_dedup_multi_iter_next_ip4_route(NMDedupMultiIter * ipconf_iter, - const NMPlatformIP4Route **out_route) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(ipconf_iter); - if (out_route) - *out_route = has_next ? NMP_OBJECT_CAST_IP4_ROUTE(ipconf_iter->current->obj) : NULL; - return has_next; -} - -static inline gboolean -nm_platform_dedup_multi_iter_next_ip6_address(NMDedupMultiIter * ipconf_iter, - const NMPlatformIP6Address **out_address) -{ - gboolean has_next; - - has_next = nm_dedup_multi_iter_next(ipconf_iter); - if (out_address) - *out_address = has_next ? NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter->current->obj) : NULL; - return has_next; -} - -static inline gboolean -nm_platform_dedup_multi_iter_next_ip6_route(NMDedupMultiIter * ipconf_iter, - const NMPlatformIP6Route **out_route) -{ - gboolean has_next; +#define _nm_platform_dedup_multi_iter_next(ipconf_iter, out_obj, field, ...) \ + ({ \ + NMDedupMultiIter *const _ipconf_iter = (ipconf_iter); \ + const typeof(((NMPObject *) NULL)->field) **const _out_obj = (out_obj); \ + gboolean _has_next; \ + \ + if (G_LIKELY(nm_dedup_multi_iter_next(_ipconf_iter))) { \ + if (_out_obj) { \ + *_out_obj = _NMP_OBJECT_CAST(_ipconf_iter->current->obj, field, __VA_ARGS__); \ + } else { \ + nm_assert( \ + NM_IN_SET(NMP_OBJECT_GET_TYPE(_ipconf_iter->current->obj), __VA_ARGS__)); \ + } \ + _has_next = TRUE; \ + } else { \ + if (_out_obj) \ + *_out_obj = NULL; \ + _has_next = FALSE; \ + } \ + _has_next; \ + }) - has_next = nm_dedup_multi_iter_next(ipconf_iter); - if (out_route) - *out_route = has_next ? NMP_OBJECT_CAST_IP6_ROUTE(ipconf_iter->current->obj) : NULL; - return has_next; -} +#define nm_platform_dedup_multi_iter_next_ip_address(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip_address, \ + NMP_OBJECT_TYPE_IP4_ADDRESS, \ + NMP_OBJECT_TYPE_IP6_ADDRESS) + +#define nm_platform_dedup_multi_iter_next_ip4_address(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip4_address, \ + NMP_OBJECT_TYPE_IP4_ADDRESS) + +#define nm_platform_dedup_multi_iter_next_ip6_address(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip6_address, \ + NMP_OBJECT_TYPE_IP6_ADDRESS) + +#define nm_platform_dedup_multi_iter_next_ip_route(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip_route, \ + NMP_OBJECT_TYPE_IP4_ROUTE, \ + NMP_OBJECT_TYPE_IP6_ROUTE) + +#define nm_platform_dedup_multi_iter_next_ip4_route(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip4_route, \ + NMP_OBJECT_TYPE_IP4_ROUTE) + +#define nm_platform_dedup_multi_iter_next_ip6_route(ipconf_iter, out_obj) \ + _nm_platform_dedup_multi_iter_next((ipconf_iter), \ + (out_obj), \ + ip6_route, \ + NMP_OBJECT_TYPE_IP6_ROUTE) #endif /* __NMP_OBJECT_H__ */ diff --git a/src/platform/nmp-rules-manager.c b/src/core/platform/nmp-rules-manager.c index d139c9a3..0c617b80 100644 --- a/src/platform/nmp-rules-manager.c +++ b/src/core/platform/nmp-rules-manager.c @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nmp-rules-manager.h" diff --git a/src/platform/nmp-rules-manager.h b/src/core/platform/nmp-rules-manager.h index 29c1295c..69cf9075 100644 --- a/src/platform/nmp-rules-manager.h +++ b/src/core/platform/nmp-rules-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef __NMP_RULES_MANAGER_H__ #define __NMP_RULES_MANAGER_H__ diff --git a/src/platform/tests/meson.build b/src/core/platform/tests/meson.build index f96850cc..5d55707a 100644 --- a/src/platform/tests/meson.build +++ b/src/core/platform/tests/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_fake_c_flags = test_c_flags + ['-DSETUP=nm_fake_platform_setup'] test_linux_c_flags = test_c_flags + ['-DSETUP=nm_linux_platform_setup'] @@ -22,7 +22,7 @@ foreach test_unit: test_units exe = executable( test_unit[0], test_unit[1], - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_unit[2], ) test( @@ -38,6 +38,6 @@ name = 'monitor' executable( name, name + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/platform/tests/monitor.c b/src/core/platform/tests/monitor.c index a8d0fad2..abdf2cd5 100644 --- a/src/platform/tests/monitor.c +++ b/src/core/platform/tests/monitor.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdlib.h> #include <syslog.h> diff --git a/src/platform/tests/test-address.c b/src/core/platform/tests/test-address.c index 5ea30a57..d4d67105 100644 --- a/src/platform/tests/test-address.c +++ b/src/core/platform/tests/test-address.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "test-common.h" diff --git a/src/platform/tests/test-cleanup.c b/src/core/platform/tests/test-cleanup.c index c364bfa1..b54eca34 100644 --- a/src/platform/tests/test-cleanup.c +++ b/src/core/platform/tests/test-cleanup.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "test-common.h" diff --git a/src/platform/tests/test-common.c b/src/core/platform/tests/test-common.c index fb430046..87e5329a 100644 --- a/src/platform/tests/test-common.c +++ b/src/core/platform/tests/test-common.c @@ -1,9 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" + +#include "test-common.h" #include <sys/mount.h> #include <sched.h> @@ -11,7 +13,7 @@ #include <fcntl.h> #include <linux/if_tun.h> -#include "test-common.h" +#include "n-acd/src/n-acd.h" #define SIGNAL_DATA_FMT "'%s-%s' ifindex %d%s%s%s (%d times received)" #define SIGNAL_DATA_ARG(data) \ @@ -87,7 +89,7 @@ nmtstp_platform_ip6_address_get_all(NMPlatform *self, int ifindex) const NMPlatformIPAddress * nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, gconstpointer addr) { - const gboolean IS_IPv4 = NM_IS_IPv4(addr_family); + const int IS_IPv4 = NM_IS_IPv4(addr_family); const NMPlatformIPAddress *found = NULL; NMDedupMultiIter iter; const NMPObject * obj; @@ -99,8 +101,7 @@ nmtstp_platform_ip_address_find(NMPlatform *self, int ifindex, int addr_family, nm_assert(addr); nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex); - nm_platform_iter_obj_for_each(&iter, self, &lookup, &obj) - { + nm_platform_iter_obj_for_each (&iter, self, &lookup, &obj) { const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS(obj); g_assert(NMP_OBJECT_GET_ADDR_FAMILY(obj) == addr_family); @@ -1478,7 +1479,7 @@ nmtstp_link_bridge_add(NMPlatform * platform, lnk->group_fwd_mask != 0 ? nm_sprintf_buf(sbuf_gfw, "group_fwd_mask %#x ", lnk->group_fwd_mask) : "", - NM_ETHER_ADDR_FORMAT_VAL(lnk->group_addr), + NM_ETHER_ADDR_FORMAT_VAL(&lnk->group_addr), (int) lnk->mcast_snooping, lnk->mcast_router, (int) lnk->mcast_query_use_ifaddr, @@ -1571,8 +1572,8 @@ nmtstp_link_veth_add(NMPlatform *platform, const char *name, const char *peer) { - const NMPlatformLink *pllink = NULL; - gboolean success; + const NMPlatformLink *pllink = NULL; + gboolean success = FALSE; g_assert(nm_utils_ifname_valid_kernel(name, NULL)); @@ -1585,9 +1586,28 @@ nmtstp_link_veth_add(NMPlatform *platform, if (success) { pllink = nmtstp_assert_wait_for_link(platform, name, NM_LINK_TYPE_VETH, 100); nmtstp_assert_wait_for_link(platform, peer, NM_LINK_TYPE_VETH, 10); + } else { + /* iproute2 might fail in copr. See below. + * We accept that and try our platform implementation instead. */ + _LOGI("iproute2 failed to add veth device. Retry with platform code."); + external_command = FALSE; } - } else - success = NMTST_NM_ERR_SUCCESS(nm_platform_link_veth_add(platform, name, peer, &pllink)); + } + + if (!external_command) { + int try_count = 0; + int r; + +again: + r = nm_platform_link_veth_add(platform, name, peer, &pllink); + if (r == -EPERM && try_count++ < 5) { + /* in copr (mock with Fedora 33 builders), this randomly fails with EPERM. + * Very odd. Try to work around by retrying. */ + _LOGI("netlink failuer EPERM to add veth device. Retry."); + goto again; + } + success = NMTST_NM_ERR_SUCCESS(r); + } g_assert(success); _assert_pllink(platform, success, pllink, name, NM_LINK_TYPE_VETH); @@ -2254,18 +2274,18 @@ gboolean nmtstp_kernel_support_get(NMPlatformKernelSupportType type) { const NMPlatformLink *pllink; - NMTernary v; + NMOptionBool v; v = nm_platform_kernel_support_get_full(type, FALSE); - if (v != NM_TERNARY_DEFAULT) - return v != NM_TERNARY_FALSE; + if (v != NM_OPTION_BOOL_DEFAULT) + return v != NM_OPTION_BOOL_FALSE; switch (type) { case NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BR_VLAN_STATS_ENABLED: pllink = nmtstp_link_bridge_add(NULL, -1, "br-test-11", &nm_platform_lnk_bridge_default); nmtstp_link_delete(NULL, -1, pllink->ifindex, NULL, TRUE); v = nm_platform_kernel_support_get_full(type, FALSE); - g_assert(v != NM_TERNARY_DEFAULT); + g_assert(v != NM_OPTION_BOOL_DEFAULT); return v; default: g_assert_not_reached(); @@ -2567,3 +2587,145 @@ main(int argc, char **argv) g_object_unref(NM_PLATFORM_GET); return result; } + +/*****************************************************************************/ + +struct _NMTstpAcdDefender { + int ifindex; + in_addr_t ip_addr; + NAcd * nacd; + NAcdProbe *probe; + GSource * source; + gint8 announce_started; +}; + +static gboolean +_l3_acd_nacd_event(int fd, GIOCondition condition, gpointer user_data) +{ + NMTstpAcdDefender *defender = user_data; + int r; + + r = n_acd_dispatch(defender->nacd); + if (r == N_ACD_E_PREEMPTED) + r = 0; + g_assert_cmpint(r, ==, 0); + + while (TRUE) { + NAcdEvent *event; + + r = n_acd_pop_event(defender->nacd, &event); + g_assert_cmpint(r, ==, 0); + if (!event) + return G_SOURCE_CONTINUE; + + switch (event->event) { + case N_ACD_EVENT_READY: + g_assert_cmpint(defender->announce_started, ==, 0); + g_assert(defender->probe == event->ready.probe); + defender->announce_started++; + _LOGT("acd-defender[" NM_HASH_OBFUSCATE_PTR_FMT "]: start announcing", + NM_HASH_OBFUSCATE_PTR(defender)); + r = n_acd_probe_announce(defender->probe, N_ACD_DEFEND_ALWAYS); + g_assert_cmpint(r, ==, 0); + break; + case N_ACD_EVENT_DEFENDED: + g_assert(defender->probe == event->defended.probe); + g_assert_cmpint(event->defended.n_sender, ==, ETH_ALEN); + _LOGT("acd-defender[" NM_HASH_OBFUSCATE_PTR_FMT + "]: defended from " NM_ETHER_ADDR_FORMAT_STR, + NM_HASH_OBFUSCATE_PTR(defender), + NM_ETHER_ADDR_FORMAT_VAL((const NMEtherAddr *) event->defended.sender)); + break; + case N_ACD_EVENT_USED: + case N_ACD_EVENT_CONFLICT: + case N_ACD_EVENT_DOWN: + default: + g_assert_not_reached(); + break; + } + } +} + +NMTstpAcdDefender * +nmtstp_acd_defender_new(int ifindex, in_addr_t ip_addr, const NMEtherAddr *mac_addr) +{ + NMTstpAcdDefender * defender; + nm_auto(n_acd_config_freep) NAcdConfig * config = NULL; + nm_auto(n_acd_unrefp) NAcd * nacd = NULL; + nm_auto(n_acd_probe_config_freep) NAcdProbeConfig *probe_config = NULL; + NAcdProbe * probe = NULL; + int fd; + int r; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + g_assert_cmpint(ifindex, >, 0); + g_assert(mac_addr); + + r = n_acd_config_new(&config); + g_assert_cmpint(r, ==, 0); + g_assert(config); + + n_acd_config_set_ifindex(config, ifindex); + n_acd_config_set_transport(config, N_ACD_TRANSPORT_ETHERNET); + n_acd_config_set_mac(config, (const guint8 *) mac_addr, sizeof(*mac_addr)); + + r = n_acd_new(&nacd, config); + g_assert_cmpint(r, ==, 0); + g_assert(nacd); + + r = n_acd_probe_config_new(&probe_config); + g_assert_cmpint(r, ==, 0); + g_assert(probe_config); + + n_acd_probe_config_set_ip(probe_config, (struct in_addr){ip_addr}); + n_acd_probe_config_set_timeout(probe_config, 0); + + r = n_acd_probe(nacd, &probe, probe_config); + g_assert_cmpint(r, ==, 0); + g_assert(probe); + + defender = g_slice_new(NMTstpAcdDefender); + *defender = (NMTstpAcdDefender){ + .ifindex = ifindex, + .ip_addr = ip_addr, + .nacd = g_steal_pointer(&nacd), + .probe = g_steal_pointer(&probe), + }; + + _LOGT("acd-defender[" NM_HASH_OBFUSCATE_PTR_FMT + "]: new for ifindex=%d, hwaddr=" NM_ETHER_ADDR_FORMAT_STR ", ipaddr=%s", + NM_HASH_OBFUSCATE_PTR(defender), + ifindex, + NM_ETHER_ADDR_FORMAT_VAL(mac_addr), + _nm_utils_inet4_ntop(ip_addr, sbuf_addr)); + + n_acd_probe_set_userdata(defender->probe, defender); + + n_acd_get_fd(defender->nacd, &fd); + g_assert_cmpint(fd, >=, 0); + + defender->source = nm_g_source_attach(nm_g_unix_fd_source_new(fd, + G_IO_IN, + G_PRIORITY_DEFAULT, + _l3_acd_nacd_event, + defender, + NULL), + NULL); + + return defender; +} + +void +nmtstp_acd_defender_destroy(NMTstpAcdDefender *defender) +{ + if (!defender) + return; + + _LOGT("acd-defender[" NM_HASH_OBFUSCATE_PTR_FMT "]: destroy", NM_HASH_OBFUSCATE_PTR(defender)); + + nm_clear_g_source_inst(&defender->source); + nm_clear_pointer(&defender->nacd, n_acd_unref); + nm_clear_pointer(&defender->probe, n_acd_probe_free); + + nm_g_slice_free(defender); +} diff --git a/src/platform/tests/test-common.h b/src/core/platform/tests/test-common.h index 1d996f46..618645fe 100644 --- a/src/platform/tests/test-common.h +++ b/src/core/platform/tests/test-common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ @@ -606,5 +606,14 @@ void nmtstp_setup_platform(void); /*****************************************************************************/ +typedef struct _NMTstpAcdDefender NMTstpAcdDefender; + +NMTstpAcdDefender * +nmtstp_acd_defender_new(int ifindex, in_addr_t ip_addr, const NMEtherAddr *mac_addr); + +void nmtstp_acd_defender_destroy(NMTstpAcdDefender *defender); + +/*****************************************************************************/ + void _nmtstp_init_tests(int *argc, char ***argv); void _nmtstp_setup_tests(void); diff --git a/src/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 5fd67ec4..3aaa3759 100644 --- a/src/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <sched.h> #include <sys/mount.h> @@ -12,9 +12,10 @@ #include <linux/if_tun.h> #include "nm-glib-aux/nm-io-utils.h" +#include "nm-base/nm-ethtool-base.h" #include "platform/nmp-object.h" -#include "platform/nmp-netns.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nmp-netns.h" +#include "nm-platform/nm-platform-utils.h" #include "test-common.h" #include "nm-test-utils-core.h" @@ -3676,25 +3677,28 @@ test_ethtool_features_get(void) for (i_run = 0; i_run < 5; i_run++) { NMEthtoolFeatureStates *features; - NMTernary * requested; + NMOptionBool * requested; gboolean do_set = TRUE; - requested = g_new(NMTernary, _NM_ETHTOOL_ID_FEATURE_NUM); + requested = g_new(NMOptionBool, _NM_ETHTOOL_ID_FEATURE_NUM); for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) - requested[i] = NM_TERNARY_DEFAULT; + requested[i] = NM_OPTION_BOOL_DEFAULT; g_ptr_array_add(gfree_keeper, requested); if (i_run == 0) { - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_RX)] = NM_TERNARY_FALSE; - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_RX)] = + NM_OPTION_BOOL_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = + NM_OPTION_BOOL_FALSE; requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = - NM_TERNARY_FALSE; + NM_OPTION_BOOL_FALSE; } else if (i_run == 1) do_set = FALSE; else if (i_run == 2) { - requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = NM_TERNARY_FALSE; + requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TSO)] = + NM_OPTION_BOOL_FALSE; requested[_NM_ETHTOOL_ID_FEATURE_AS_IDX(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION)] = - NM_TERNARY_TRUE; + NM_OPTION_BOOL_TRUE; } else if (i_run == 3) do_set = FALSE; diff --git a/src/platform/tests/test-nmp-object.c b/src/core/platform/tests/test-nmp-object.c index e61e6b09..310611ee 100644 --- a/src/platform/tests/test-nmp-object.c +++ b/src/core/platform/tests/test-nmp-object.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <libudev.h> #include <linux/pkt_sched.h> @@ -569,7 +569,7 @@ main(int argc, char **argv) nmtst_init_assert_logging(&argc, &argv, "INFO", "DEFAULT"); - udev_client = nm_udev_client_new((const char *[]){"net", NULL}, NULL, NULL); + udev_client = nm_udev_client_new(NM_MAKE_STRV("net"), NULL, NULL); { struct udev_enumerate * enumerator; struct udev_list_entry *devices, *l; @@ -611,7 +611,7 @@ main(int argc, char **argv) global.udev_devices = g_list_delete_link(global.udev_devices, global.udev_devices); } - nm_udev_client_unref(udev_client); + nm_udev_client_destroy(udev_client); return result; } diff --git a/src/platform/tests/test-platform-general.c b/src/core/platform/tests/test-platform-general.c index 703c886e..b426cc65 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/core/platform/tests/test-platform-general.c @@ -1,13 +1,13 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <linux/rtnetlink.h> -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "platform/nm-linux-platform.h" #include "nm-test-utils-core.h" diff --git a/src/platform/tests/test-route.c b/src/core/platform/tests/test-route.c index 1305e586..47587865 100644 --- a/src/platform/tests/test-route.c +++ b/src/core/platform/tests/test-route.c @@ -1,15 +1,15 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <linux/rtnetlink.h> #include <linux/fib_rules.h> #include "nm-core-utils.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "platform/nmp-rules-manager.h" #include "test-common.h" diff --git a/src/platform/tests/test-tc.c b/src/core/platform/tests/test-tc.c index 4cbe4f5d..d15c3d76 100644 --- a/src/platform/tests/test-tc.c +++ b/src/core/platform/tests/test-tc.c @@ -1,13 +1,13 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <linux/pkt_sched.h> #include "nm-test-utils-core.h" #include "platform/nmp-object.h" -#include "platform/nmp-netns.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nmp-netns.h" +#include "nm-platform/nm-platform-utils.h" #include "test-common.h" static NMPObject * diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.c b/src/core/platform/wifi/nm-wifi-utils-nl80211.c index dddfa8fa..ad067248 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.c +++ b/src/core/platform/wifi/nm-wifi-utils-nl80211.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. * Copyright (C) 2011 Intel Corporation. All rights reserved. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-utils-nl80211.h" @@ -15,10 +15,10 @@ #include <linux/nl80211.h> #include <linux/if.h> -#include "platform/nm-netlink.h" +#include "nm-platform/nm-netlink.h" #include "nm-wifi-utils-private.h" #include "platform/nm-platform.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-utils.h" #define _NMLOG_PREFIX_NAME "wifi-nl80211" @@ -163,6 +163,7 @@ dispose(GObject *object) struct nl80211_iface_info { NM80211Mode mode; + uint32_t freq; }; static int @@ -193,6 +194,9 @@ nl80211_iface_info_handler(struct nl_msg *msg, void *arg) break; } + if (tb[NL80211_ATTR_WIPHY_FREQ] != NULL) + info->freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]); + return NL_SKIP; } @@ -359,142 +363,19 @@ nla_put_failure: g_return_val_if_reached(FALSE); } -/* @divisor: pass what value @xbm should be divided by to get dBm */ -static guint32 -nl80211_xbm_to_percent(gint32 xbm, guint32 divisor) -{ -#define NOISE_FLOOR_DBM -90 -#define SIGNAL_MAX_DBM -20 - - xbm /= divisor; - xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM); - - return 100 - - 70 - * (((float) SIGNAL_MAX_DBM - (float) xbm) - / ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); -} - -struct nl80211_bss_info { - guint32 freq; - guint8 bssid[ETH_ALEN]; - guint8 ssid[32]; - guint32 ssid_len; - guint32 beacon_signal; - gboolean valid; -}; - -#define WLAN_EID_SSID 0 - -static void -find_ssid(guint8 *ies, guint32 ies_len, guint8 **ssid, guint32 *ssid_len) -{ - *ssid = NULL; - *ssid_len = 0; - - while (ies_len > 2 && ies[0] != WLAN_EID_SSID) { - ies_len -= ies[1] + 2; - ies += ies[1] + 2; - } - if (ies_len < 2) - return; - if (ies_len < 2 + ies[1]) - return; - - *ssid_len = ies[1]; - *ssid = ies + 2; -} - -static int -nl80211_bss_dump_handler(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy bss_policy[] = { - [NL80211_BSS_TSF] = {.type = NLA_U64}, - [NL80211_BSS_FREQUENCY] = {.type = NLA_U32}, - [NL80211_BSS_BSSID] = {.minlen = ETH_ALEN}, - [NL80211_BSS_BEACON_INTERVAL] = {.type = NLA_U16}, - [NL80211_BSS_CAPABILITY] = {.type = NLA_U16}, - [NL80211_BSS_INFORMATION_ELEMENTS] = {}, - [NL80211_BSS_SIGNAL_MBM] = {.type = NLA_U32}, - [NL80211_BSS_SIGNAL_UNSPEC] = {.type = NLA_U8}, - [NL80211_BSS_STATUS] = {.type = NLA_U32}, - }; - struct nl80211_bss_info *info = arg; - struct genlmsghdr * gnlh = nlmsg_data(nlmsg_hdr(msg)); - struct nlattr * tb[NL80211_ATTR_MAX + 1]; - struct nlattr * bss[G_N_ELEMENTS(bss_policy)]; - guint32 status; - - if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) - return NL_SKIP; - - if (tb[NL80211_ATTR_BSS] == NULL) - return NL_SKIP; - - if (nla_parse_nested_arr(bss, tb[NL80211_ATTR_BSS], bss_policy)) - return NL_SKIP; - - if (bss[NL80211_BSS_STATUS] == NULL) - return NL_SKIP; - - status = nla_get_u32(bss[NL80211_BSS_STATUS]); - - if (status != NL80211_BSS_STATUS_ASSOCIATED && status != NL80211_BSS_STATUS_IBSS_JOINED) - return NL_SKIP; - - if (bss[NL80211_BSS_BSSID] == NULL) - return NL_SKIP; - memcpy(info->bssid, nla_data(bss[NL80211_BSS_BSSID]), ETH_ALEN); - - if (bss[NL80211_BSS_FREQUENCY]) - info->freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]); - - if (bss[NL80211_BSS_SIGNAL_UNSPEC]) - info->beacon_signal = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); - - if (bss[NL80211_BSS_SIGNAL_MBM]) - info->beacon_signal = nl80211_xbm_to_percent(nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]), 100); - - if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) { - guint8 *ssid; - guint32 ssid_len; - - find_ssid(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), - nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), - &ssid, - &ssid_len); - if (ssid && ssid_len && ssid_len <= sizeof(info->ssid)) { - memcpy(info->ssid, ssid, ssid_len); - info->ssid_len = ssid_len; - } - } - - info->valid = TRUE; - - return NL_SKIP; -} - -static void -nl80211_get_bss_info(NMWifiUtilsNl80211 *self, struct nl80211_bss_info *bss_info) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - - memset(bss_info, 0, sizeof(*bss_info)); - - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_SCAN, NLM_F_DUMP); - - nl80211_send_and_recv(self, msg, nl80211_bss_dump_handler, bss_info); -} - static guint32 wifi_nl80211_get_freq(NMWifiUtils *data) { - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_bss_info bss_info; + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + struct nl80211_iface_info iface_info = {}; + nm_auto_nlmsg struct nl_msg *msg = NULL; - nl80211_get_bss_info(self, &bss_info); + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_INTERFACE, 0); + + if (nl80211_send_and_recv(self, msg, nl80211_iface_info_handler, &iface_info) < 0) + return 0; - return bss_info.freq; + return iface_info.freq; } static guint32 @@ -513,21 +394,25 @@ wifi_nl80211_find_freq(NMWifiUtils *data, const guint32 *freqs) return 0; } -static gboolean -wifi_nl80211_get_bssid(NMWifiUtils *data, guint8 *out_bssid) +/* @divisor: pass what value @xbm should be divided by to get dBm */ +static guint32 +nl80211_xbm_to_percent(gint32 xbm, guint32 divisor) { - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_bss_info bss_info; - - nl80211_get_bss_info(self, &bss_info); +#define NOISE_FLOOR_DBM -90 +#define SIGNAL_MAX_DBM -20 - if (bss_info.valid) - memcpy(out_bssid, bss_info.bssid, ETH_ALEN); + xbm /= divisor; + xbm = CLAMP(xbm, NOISE_FLOOR_DBM, SIGNAL_MAX_DBM); - return bss_info.valid; + return 100 + - 70 + * (((float) SIGNAL_MAX_DBM - (float) xbm) + / ((float) SIGNAL_MAX_DBM - (float) NOISE_FLOOR_DBM)); } struct nl80211_station_info { + gboolean valid; + guint8 bssid[ETH_ALEN]; guint32 txrate; gboolean txrate_valid; guint8 signal; @@ -535,19 +420,21 @@ struct nl80211_station_info { }; static int -nl80211_station_handler(struct nl_msg *msg, void *arg) +nl80211_station_dump_handler(struct nl_msg *msg, void *arg) { static const struct nla_policy stats_policy[] = { - [NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32}, - [NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32}, - [NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32}, - [NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32}, - [NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32}, - [NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8}, - [NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED}, - [NL80211_STA_INFO_LLID] = {.type = NLA_U16}, - [NL80211_STA_INFO_PLID] = {.type = NLA_U16}, - [NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8}, + [NL80211_STA_INFO_INACTIVE_TIME] = {.type = NLA_U32}, + [NL80211_STA_INFO_RX_BYTES] = {.type = NLA_U32}, + [NL80211_STA_INFO_TX_BYTES] = {.type = NLA_U32}, + [NL80211_STA_INFO_RX_PACKETS] = {.type = NLA_U32}, + [NL80211_STA_INFO_TX_PACKETS] = {.type = NLA_U32}, + [NL80211_STA_INFO_SIGNAL] = {.type = NLA_U8}, + [NL80211_STA_INFO_TX_BITRATE] = {.type = NLA_NESTED}, + [NL80211_STA_INFO_LLID] = {.type = NLA_U16}, + [NL80211_STA_INFO_PLID] = {.type = NLA_U16}, + [NL80211_STA_INFO_PLINK_STATE] = {.type = NLA_U8}, + [NL80211_STA_INFO_STA_FLAGS] = {.minlen = sizeof(struct nl80211_sta_flag_update)}, + [NL80211_STA_INFO_BEACON_SIGNAL_AVG] = {.type = NLA_U8}, }; static const struct nla_policy rate_policy[] = { [NL80211_RATE_INFO_BITRATE] = {.type = NLA_U16}, @@ -564,80 +451,76 @@ nl80211_station_handler(struct nl_msg *msg, void *arg) if (nla_parse_arr(tb, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL) < 0) return NL_SKIP; + if (tb[NL80211_ATTR_MAC] == NULL) + return NL_SKIP; + if (tb[NL80211_ATTR_STA_INFO] == NULL) return NL_SKIP; if (nla_parse_nested_arr(sinfo, tb[NL80211_ATTR_STA_INFO], stats_policy)) return NL_SKIP; - if (sinfo[NL80211_STA_INFO_TX_BITRATE] == NULL) - return NL_SKIP; + if (sinfo[NL80211_STA_INFO_STA_FLAGS] != NULL) { + const struct nl80211_sta_flag_update *flags = nla_data(sinfo[NL80211_STA_INFO_STA_FLAGS]); - if (nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy)) - return NL_SKIP; + if (flags->mask & ~flags->set & (1 << NL80211_STA_FLAG_ASSOCIATED)) + return NL_SKIP; + } - if (rinfo[NL80211_RATE_INFO_BITRATE] == NULL) - return NL_SKIP; + memcpy(info->bssid, nla_data(tb[NL80211_ATTR_MAC]), ETH_ALEN); + info->valid = TRUE; - /* convert from nl80211's units of 100kbps to NM's kbps */ - info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100; - info->txrate_valid = TRUE; + if (sinfo[NL80211_STA_INFO_TX_BITRATE] != NULL + && !nla_parse_nested_arr(rinfo, sinfo[NL80211_STA_INFO_TX_BITRATE], rate_policy) + && rinfo[NL80211_RATE_INFO_BITRATE] != NULL) { + /* convert from nl80211's units of 100kbps to NM's kbps */ + info->txrate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]) * 100; + info->txrate_valid = TRUE; + } if (sinfo[NL80211_STA_INFO_SIGNAL] != NULL) { info->signal = nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]), 1); info->signal_valid = TRUE; + } else if (sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG] != NULL) { + /* Fall back to beacon signal strength */ + info->signal = + nl80211_xbm_to_percent((gint8) nla_get_u8(sinfo[NL80211_STA_INFO_BEACON_SIGNAL_AVG]), + 1); + info->signal_valid = TRUE; } return NL_SKIP; } -static void -nl80211_get_ap_info(NMWifiUtilsNl80211 *self, struct nl80211_station_info *sta_info) +static gboolean +wifi_nl80211_get_station(NMWifiUtils *data, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - struct nl80211_bss_info bss_info; - - memset(sta_info, 0, sizeof(*sta_info)); + NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; + nm_auto_nlmsg struct nl_msg *msg = NULL; + struct nl80211_station_info sta_info = {}; - nl80211_get_bss_info(self, &bss_info); - if (!bss_info.valid) - return; + msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, NLM_F_DUMP); - msg = nl80211_alloc_msg(self, NL80211_CMD_GET_STATION, 0); - NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bss_info.bssid); - - nl80211_send_and_recv(self, msg, nl80211_station_handler, sta_info); - if (!sta_info->signal_valid) { - /* Fall back to bss_info signal quality (both are in percent) */ - sta_info->signal = bss_info.beacon_signal; - } - - return; - -nla_put_failure: - g_return_if_reached(); -} + nl80211_send_and_recv(self, msg, nl80211_station_dump_handler, &sta_info); -static guint32 -wifi_nl80211_get_rate(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_station_info sta_info; + if (!sta_info.valid || (out_quality && !sta_info.signal_valid) + || (out_rate && !sta_info.txrate_valid)) + return FALSE; - nl80211_get_ap_info(self, &sta_info); + if (out_bssid) + memcpy(out_bssid, sta_info.bssid, ETH_ALEN); - return sta_info.txrate; -} + if (out_quality) + *out_quality = sta_info.signal; -static int -wifi_nl80211_get_qual(NMWifiUtils *data) -{ - NMWifiUtilsNl80211 * self = (NMWifiUtilsNl80211 *) data; - struct nl80211_station_info sta_info; + if (out_rate) + *out_rate = sta_info.txrate; - nl80211_get_ap_info(self, &sta_info); - return sta_info.signal; + return TRUE; } static gboolean @@ -952,9 +835,7 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass) wifi_utils_class->set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan, wifi_utils_class->get_freq = wifi_nl80211_get_freq; wifi_utils_class->find_freq = wifi_nl80211_find_freq; - wifi_utils_class->get_bssid = wifi_nl80211_get_bssid; - wifi_utils_class->get_rate = wifi_nl80211_get_rate; - wifi_utils_class->get_qual = wifi_nl80211_get_qual; + wifi_utils_class->get_station = wifi_nl80211_get_station; wifi_utils_class->indicate_addressing_running = wifi_nl80211_indicate_addressing_running; wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel; wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel; diff --git a/src/platform/wifi/nm-wifi-utils-nl80211.h b/src/core/platform/wifi/nm-wifi-utils-nl80211.h index 59fc1acc..37c32ed7 100644 --- a/src/platform/wifi/nm-wifi-utils-nl80211.h +++ b/src/core/platform/wifi/nm-wifi-utils-nl80211.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 Intel Corporation. All rights reserved. * Copyright (C) 2018 Red Hat, Inc. @@ -8,7 +8,7 @@ #define __WIFI_UTILS_NL80211_H__ #include "nm-wifi-utils.h" -#include "platform/nm-netlink.h" +#include "nm-platform/nm-netlink.h" #define NM_TYPE_WIFI_UTILS_NL80211 (nm_wifi_utils_nl80211_get_type()) #define NM_WIFI_UTILS_NL80211(obj) \ diff --git a/src/platform/wifi/nm-wifi-utils-private.h b/src/core/platform/wifi/nm-wifi-utils-private.h index 1a5303a6..9ed57453 100644 --- a/src/platform/wifi/nm-wifi-utils-private.h +++ b/src/core/platform/wifi/nm-wifi-utils-private.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ @@ -31,15 +31,17 @@ typedef struct { /* Return first supported frequency in the zero-terminated list */ guint32 (*find_freq)(NMWifiUtils *data, const guint32 *freqs); - /* Return current bitrate in Kbps */ - guint32 (*get_rate)(NMWifiUtils *data); - - gboolean (*get_bssid)(NMWifiUtils *data, guint8 *out_bssid); - - /* Return a signal strength percentage 0 - 100% for the current BSSID; - * return -1 on errors or if not associated. + /* + * @out_bssid: must be NULL or an ETH_ALEN-byte buffer + * @out_quality: receives signal strength percentage 0 - 100% for the current BSSID, if not NULL + * @out_rate: receives current bitrate in Kbps if not NULL + * + * Returns %TRUE on succcess, %FALSE on errors or if not associated. */ - int (*get_qual)(NMWifiUtils *data); + gboolean (*get_station)(NMWifiUtils *data, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate); /* OLPC Mesh-only functions */ diff --git a/src/platform/wifi/nm-wifi-utils-wext.c b/src/core/platform/wifi/nm-wifi-utils-wext.c index 8299415d..a44fcf62 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.c +++ b/src/core/platform/wifi/nm-wifi-utils-wext.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-utils-wext.h" @@ -23,8 +23,9 @@ #include "nm-wifi-utils-private.h" #include "nm-utils.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #include "nm-core-internal.h" +#include "nm-core-utils.h" typedef struct { NMWifiUtils parent; @@ -266,7 +267,7 @@ wifi_wext_find_freq(NMWifiUtils *data, const guint32 *freqs) } static gboolean -wifi_wext_get_bssid(NMWifiUtils *data, guint8 *out_bssid) +wifi_wext_get_bssid(NMWifiUtils *data, NMEtherAddr *out_bssid) { NMWifiUtilsWext *wext = (NMWifiUtilsWext *) data; struct iwreq wrq; @@ -453,6 +454,38 @@ wifi_wext_get_qual(NMWifiUtils *data) return wext_qual_to_percent(&stats.qual, &wext->max_qual); } +static gboolean +wifi_wext_get_station(NMWifiUtils *data, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate) +{ + NMEtherAddr local_addr; + + if (!out_bssid && !out_quality && !out_rate) { + /* hm, the caller requested no parameter at all? + * Don't simply return TRUE, but at least check that + * we can successfully fetch the bssid. */ + out_bssid = &local_addr; + } + + if (out_bssid) { + if (!wifi_wext_get_bssid(data, out_bssid)) + return FALSE; + } + if (out_quality) { + *out_quality = wifi_wext_get_qual(data); + if (*out_quality < 0) + return FALSE; + } + if (out_rate) { + *out_rate = wifi_wext_get_rate(data); + if (*out_rate == 0) + return FALSE; + } + return TRUE; +} + /*****************************************************************************/ /* OLPC Mesh-only functions */ @@ -677,9 +710,7 @@ nm_wifi_utils_wext_class_init(NMWifiUtilsWextClass *klass) wifi_utils_class->set_powersave = wifi_wext_set_powersave; wifi_utils_class->get_freq = wifi_wext_get_freq; wifi_utils_class->find_freq = wifi_wext_find_freq; - wifi_utils_class->get_bssid = wifi_wext_get_bssid; - wifi_utils_class->get_rate = wifi_wext_get_rate; - wifi_utils_class->get_qual = wifi_wext_get_qual; + wifi_utils_class->get_station = wifi_wext_get_station; wifi_utils_class->get_mesh_channel = wifi_wext_get_mesh_channel; wifi_utils_class->set_mesh_channel = wifi_wext_set_mesh_channel; wifi_utils_class->set_mesh_ssid = wifi_wext_set_mesh_ssid; diff --git a/src/platform/wifi/nm-wifi-utils-wext.h b/src/core/platform/wifi/nm-wifi-utils-wext.h index 210b87e5..d6f3453c 100644 --- a/src/platform/wifi/nm-wifi-utils-wext.h +++ b/src/core/platform/wifi/nm-wifi-utils-wext.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2011 - 2018 Red Hat, Inc. */ diff --git a/src/platform/wifi/nm-wifi-utils.c b/src/core/platform/wifi/nm-wifi-utils.c index 3f9d3a48..49ae1811 100644 --- a/src/platform/wifi/nm-wifi-utils.c +++ b/src/core/platform/wifi/nm-wifi-utils.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wifi-utils.h" @@ -19,7 +19,7 @@ #endif #include "nm-core-utils.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" G_DEFINE_ABSTRACT_TYPE(NMWifiUtils, nm_wifi_utils, G_TYPE_OBJECT) @@ -132,27 +132,14 @@ nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs) } gboolean -nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid) +nm_wifi_utils_get_station(NMWifiUtils *data, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate) { g_return_val_if_fail(data != NULL, FALSE); - g_return_val_if_fail(out_bssid != NULL, FALSE); - memset(out_bssid, 0, ETH_ALEN); - return NM_WIFI_UTILS_GET_CLASS(data)->get_bssid(data, out_bssid); -} - -guint32 -nm_wifi_utils_get_rate(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->get_rate(data); -} - -int -nm_wifi_utils_get_qual(NMWifiUtils *data) -{ - g_return_val_if_fail(data != NULL, 0); - return NM_WIFI_UTILS_GET_CLASS(data)->get_qual(data); + return NM_WIFI_UTILS_GET_CLASS(data)->get_station(data, out_bssid, out_quality, out_rate); } gboolean diff --git a/src/platform/wifi/nm-wifi-utils.h b/src/core/platform/wifi/nm-wifi-utils.h index d1df2fb8..a252e43e 100644 --- a/src/platform/wifi/nm-wifi-utils.h +++ b/src/core/platform/wifi/nm-wifi-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2018 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -11,7 +11,7 @@ #include "nm-dbus-interface.h" #include "nm-setting-wireless.h" -#include "platform/nm-netlink.h" +#include "nm-platform/nm-netlink.h" typedef struct NMWifiUtils NMWifiUtils; @@ -43,14 +43,17 @@ guint32 nm_wifi_utils_get_freq(NMWifiUtils *data); * Frequencies are specified in MHz. */ guint32 nm_wifi_utils_find_freq(NMWifiUtils *data, const guint32 *freqs); -/* out_bssid must be ETH_ALEN bytes */ -gboolean nm_wifi_utils_get_bssid(NMWifiUtils *data, guint8 *out_bssid); - -/* Returns current bitrate in Kbps */ -guint32 nm_wifi_utils_get_rate(NMWifiUtils *data); - -/* Returns quality 0 - 100% on success, or -1 on error */ -int nm_wifi_utils_get_qual(NMWifiUtils *data); +/* + * @out_bssid: must be NULL or an ETH_ALEN-byte buffer + * @out_quality: receives signal quality in 0 - 100% range if not NULL + * @out_rate: receives current bitrate in Kbps if not NULL + * + * Returns %TRUE on succcess. + */ +gboolean nm_wifi_utils_get_station(NMWifiUtils *data, + NMEtherAddr *out_bssid, + int * out_quality, + guint32 * out_rate); /* Tells the driver DHCP or SLAAC is running */ gboolean nm_wifi_utils_indicate_addressing_running(NMWifiUtils *data, gboolean running); diff --git a/src/platform/wpan/nm-wpan-utils.c b/src/core/platform/wpan/nm-wpan-utils.c index 6f651414..efb19979 100644 --- a/src/platform/wpan/nm-wpan-utils.c +++ b/src/core/platform/wpan/nm-wpan-utils.c @@ -1,17 +1,17 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-wpan-utils.h" #include <linux/if.h> +#include "nm-platform/nm-netlink.h" #include "platform/linux/nl802154.h" -#include "platform/nm-netlink.h" -#include "platform/nm-platform-utils.h" +#include "nm-platform/nm-platform-utils.h" #define _NMLOG_PREFIX_NAME "wpan-nl802154" #define _NMLOG(level, domain, ...) \ diff --git a/src/platform/wpan/nm-wpan-utils.h b/src/core/platform/wpan/nm-wpan-utils.h index b30c89a6..940c2c9d 100644 --- a/src/platform/wpan/nm-wpan-utils.h +++ b/src/core/platform/wpan/nm-wpan-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ @@ -9,7 +9,7 @@ #include <net/ethernet.h> #include "nm-dbus-interface.h" -#include "platform/nm-netlink.h" +#include "nm-platform/nm-netlink.h" typedef struct NMWpanUtils NMWpanUtils; diff --git a/src/ppp/meson.build b/src/core/ppp/meson.build index 181a6bef..607b4718 100644 --- a/src/ppp/meson.build +++ b/src/core/ppp/meson.build @@ -1,30 +1,25 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -name = 'nm-pppd-plugin' - -c_flags = [ - '-DG_LOG_DOMAIN="@0@"'.format(name), - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', -] +# SPDX-License-Identifier: LGPL-2.1-or-later nm_pppd_plugin = shared_module( - name, + 'nm-pppd-plugin', name_prefix: '', - sources: name + '.c', + sources: 'nm-pppd-plugin.c', dependencies: libnm_core_nm_default_dep, - c_args: c_flags, + c_args: [ + '-DG_LOG_DOMAIN="nm-pppd-plugin"', + ], install: true, install_dir: pppd_plugin_dir, ) -name = 'nm-ppp-plugin' - linker_script = join_paths(meson.current_source_dir(), 'nm-ppp-plugin.ver') core_plugins += shared_module( - name, - sources: 'nm-ppp-manager.c', - dependencies: daemon_nm_default_dep, + 'nm-ppp-plugin', + sources: [ + 'nm-ppp-manager.c', + ], + dependencies: core_plugin_dep, c_args: daemon_c_flags, link_args: '-Wl,--version-script,@0@'.format(linker_script), link_depends: linker_script, diff --git a/src/ppp/nm-ppp-manager-call.c b/src/core/ppp/nm-ppp-manager-call.c index 34c3d06d..f791e8b0 100644 --- a/src/ppp/nm-ppp-manager-call.c +++ b/src/core/ppp/nm-ppp-manager-call.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ppp-manager-call.h" diff --git a/src/ppp/nm-ppp-manager-call.h b/src/core/ppp/nm-ppp-manager-call.h index d17419ba..c831cf0d 100644 --- a/src/ppp/nm-ppp-manager-call.h +++ b/src/core/ppp/nm-ppp-manager-call.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index a200334c..396a49ae 100644 --- a/src/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2012 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-ppp-manager.h" @@ -1302,8 +1302,7 @@ _ppp_manager_new(const char *iface) { g_return_val_if_fail(iface != NULL, NULL); - return ( - NMPPPManager *) g_object_new(NM_TYPE_PPP_MANAGER, NM_PPP_MANAGER_PARENT_IFACE, iface, NULL); + return g_object_new(NM_TYPE_PPP_MANAGER, NM_PPP_MANAGER_PARENT_IFACE, iface, NULL); } static void diff --git a/src/ppp/nm-ppp-manager.h b/src/core/ppp/nm-ppp-manager.h index b130608c..c41dda20 100644 --- a/src/ppp/nm-ppp-manager.h +++ b/src/core/ppp/nm-ppp-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2016 Red Hat, Inc. diff --git a/src/ppp/nm-ppp-plugin-api.h b/src/core/ppp/nm-ppp-plugin-api.h index a105690c..647e1c24 100644 --- a/src/ppp/nm-ppp-plugin-api.h +++ b/src/core/ppp/nm-ppp-plugin-api.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ diff --git a/src/ppp/nm-ppp-plugin.ver b/src/core/ppp/nm-ppp-plugin.ver index fee55787..fee55787 100644 --- a/src/ppp/nm-ppp-plugin.ver +++ b/src/core/ppp/nm-ppp-plugin.ver diff --git a/src/ppp/nm-ppp-status.h b/src/core/ppp/nm-ppp-status.h index 953bc32f..c346b119 100644 --- a/src/ppp/nm-ppp-status.h +++ b/src/core/ppp/nm-ppp-status.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2016 Red Hat, Inc. diff --git a/src/ppp/nm-pppd-plugin.c b/src/core/ppp/nm-pppd-plugin.c index f50994a3..c9016dac 100644 --- a/src/ppp/nm-pppd-plugin.c +++ b/src/core/ppp/nm-pppd-plugin.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Red Hat, Inc. @@ -20,7 +20,7 @@ #include <pppd/eui64.h> #include <pppd/ipv6cp.h> -#include "nm-default.h" +#include "nm-glib-aux/nm-default-glib.h" #include "nm-dbus-interface.h" diff --git a/src/ppp/nm-pppd-plugin.h b/src/core/ppp/nm-pppd-plugin.h index 44bb79b3..b56afbeb 100644 --- a/src/ppp/nm-pppd-plugin.h +++ b/src/core/ppp/nm-pppd-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2014 Red Hat, Inc. diff --git a/src/settings/nm-agent-manager.c b/src/core/settings/nm-agent-manager.c index 07a3dafe..7e617909 100644 --- a/src/settings/nm-agent-manager.c +++ b/src/core/settings/nm-agent-manager.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-agent-manager.h" diff --git a/src/settings/nm-agent-manager.h b/src/core/settings/nm-agent-manager.h index f4e3d139..b26af4ef 100644 --- a/src/settings/nm-agent-manager.h +++ b/src/core/settings/nm-agent-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ diff --git a/src/settings/nm-secret-agent.c b/src/core/settings/nm-secret-agent.c index 743a3467..7e7c5d7d 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/core/settings/nm-secret-agent.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-secret-agent.h" @@ -695,7 +695,7 @@ nm_secret_agent_new(GDBusMethodInvocation * context, dbus_owner = nm_auth_subject_get_unix_process_dbus_sender(subject); - self = (NMSecretAgent *) g_object_new(NM_TYPE_SECRET_AGENT, NULL); + self = g_object_new(NM_TYPE_SECRET_AGENT, NULL); priv = NM_SECRET_AGENT_GET_PRIVATE(self); diff --git a/src/settings/nm-secret-agent.h b/src/core/settings/nm-secret-agent.h index 09f60bf4..ce591425 100644 --- a/src/settings/nm-secret-agent.h +++ b/src/core/settings/nm-secret-agent.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2011 Red Hat, Inc. */ diff --git a/src/settings/nm-settings-connection.c b/src/core/settings/nm-settings-connection.c index d21b120e..0ff07189 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/core/settings/nm-settings-connection.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-settings-connection.h" diff --git a/src/settings/nm-settings-connection.h b/src/core/settings/nm-settings-connection.h index b1665cc5..7c61dbeb 100644 --- a/src/settings/nm-settings-connection.h +++ b/src/core/settings/nm-settings-connection.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2013 Red Hat, Inc. @@ -56,9 +56,9 @@ typedef enum { NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_AGENT_SECRETS = (1u << 5), NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS = (1u << 6), - /* if a profile was greated as default-wired connection for a device, then + /* if a profile was generated as default-wired connection for a device, then * when the user modifies it via D-Bus, the profile should become persisted - * to disk and it the purpose why the profile was created should be forgotten. */ + * to disk and the initial purpose the profile was created should be forgotten. */ NM_SETTINGS_CONNECTION_UPDATE_REASON_CLEAR_DEFAULT_WIRED = (1u << 7), NM_SETTINGS_CONNECTION_UPDATE_REASON_BLOCK_AUTOCONNECT = (1u << 8), diff --git a/src/settings/nm-settings-plugin.c b/src/core/settings/nm-settings-plugin.c index 79451bae..9e81caab 100644 --- a/src/settings/nm-settings-plugin.c +++ b/src/core/settings/nm-settings-plugin.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2018 Red Hat, Inc. * Copyright (C) 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-settings-plugin.h" diff --git a/src/settings/nm-settings-plugin.h b/src/core/settings/nm-settings-plugin.h index d4e8d396..a9b9b2ae 100644 --- a/src/settings/nm-settings-plugin.h +++ b/src/core/settings/nm-settings-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2007 - 2018 Red Hat, Inc. * Copyright (C) 2008 Novell, Inc. diff --git a/src/settings/nm-settings-storage.c b/src/core/settings/nm-settings-storage.c index 7fa83e21..c56ba075 100644 --- a/src/settings/nm-settings-storage.c +++ b/src/core/settings/nm-settings-storage.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-settings-storage.h" diff --git a/src/settings/nm-settings-storage.h b/src/core/settings/nm-settings-storage.h index 8f2bc3d2..970cfd77 100644 --- a/src/settings/nm-settings-storage.h +++ b/src/core/settings/nm-settings-storage.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/settings/nm-settings-utils.c b/src/core/settings/nm-settings-utils.c index 8e032c44..775d0396 100644 --- a/src/settings/nm-settings-utils.c +++ b/src/core/settings/nm-settings-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-settings-utils.h" diff --git a/src/settings/nm-settings-utils.h b/src/core/settings/nm-settings-utils.h index b03c14b0..d3f50ddf 100644 --- a/src/settings/nm-settings-utils.h +++ b/src/core/settings/nm-settings-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/settings/nm-settings.c b/src/core/settings/nm-settings.c index 6b9d5083..3d31fb8b 100644 --- a/src/settings/nm-settings.c +++ b/src/core/settings/nm-settings.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> @@ -7,7 +7,7 @@ * Copyright (C) 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-settings.h" @@ -22,7 +22,7 @@ #include "nm-libnm-core-intern/nm-common-macros.h" #include "nm-glib-aux/nm-keyfile-aux.h" -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "nm-dbus-interface.h" #include "nm-connection.h" #include "nm-setting-8021x.h" @@ -2521,17 +2521,9 @@ nm_settings_add_connection_dbus(NMSettings * self, else perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM; - /* Validate the user request */ chain = nm_auth_chain_new_subject(subject, context, pk_add_cb, self); - if (!chain) { - error = g_error_new_literal(NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_PERMISSION_DENIED, - NM_UTILS_ERROR_MSG_REQ_AUTH_FAILED); - goto done; - } c_list_link_tail(&priv->auth_lst_head, nm_auth_chain_parent_lst_list(chain)); - nm_auth_chain_set_data(chain, "perm", (gpointer) perm, NULL); nm_auth_chain_set_data(chain, "connection", g_object_ref(connection), g_object_unref); nm_auth_chain_set_data(chain, "callback", callback, NULL); diff --git a/src/settings/nm-settings.h b/src/core/settings/nm-settings.h index 3740f277..09a0af57 100644 --- a/src/settings/nm-settings.h +++ b/src/core/settings/nm-settings.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Søren Sandmann <sandmann@daimi.au.dk> * Dan Williams <dcbw@redhat.com> diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/core/settings/plugins/ifcfg-rh/meson.build index 10b93d0a..a2f11a92 100644 --- a/src/settings/plugins/ifcfg-rh/meson.build +++ b/src/core/settings/plugins/ifcfg-rh/meson.build @@ -1,49 +1,43 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later install_data( 'nm-ifcfg-rh.conf', install_dir: dbus_conf_dir, ) -name = 'nmdbus-ifcfg-rh' - dbus_sources = gnome.gdbus_codegen( - name, + 'nmdbus-ifcfg-rh', 'nm-ifcfg-rh.xml', interface_prefix: 'com.redhat', namespace: 'NMDBus', ) libnmdbus_ifcfg_rh = static_library( - name, + 'nmdbus-ifcfg-rh', sources: dbus_sources, dependencies: glib_dep, c_args: introspection_extra_cflags, ) -core_sources = files( - 'nms-ifcfg-rh-reader.c', - 'nms-ifcfg-rh-utils.c', - 'nms-ifcfg-rh-writer.c', - 'shvar.c', -) - libnms_ifcfg_rh_core = static_library( 'nms-ifcfg-rh-core', - sources: core_sources, - dependencies: daemon_nm_default_dep, + sources: files( + 'nms-ifcfg-rh-reader.c', + 'nms-ifcfg-rh-utils.c', + 'nms-ifcfg-rh-writer.c', + 'shvar.c', + ), + dependencies: core_default_dep, c_args: daemon_c_flags, ) -sources = [dbus_sources] + core_sources + files( - 'nms-ifcfg-rh-storage.c', - 'nms-ifcfg-rh-plugin.c', -) - libnm_settings_plugin_ifcfg_rh = shared_module( 'nm-settings-plugin-ifcfg-rh', - sources: sources, - dependencies: daemon_nm_default_dep, + sources: files( + 'nms-ifcfg-rh-storage.c', + 'nms-ifcfg-rh-plugin.c', + ), + dependencies: core_plugin_dep, c_args: daemon_c_flags, link_with: libnms_ifcfg_rh_core, link_args: ldflags_linker_script_settings, @@ -54,13 +48,11 @@ libnm_settings_plugin_ifcfg_rh = shared_module( core_plugins += libnm_settings_plugin_ifcfg_rh -data = [ - 'nm-ifdown', - 'nm-ifup', -] - install_data( - data, + [ + 'nm-ifdown', + 'nm-ifup', + ], install_dir: nm_libexecdir, install_mode: 'rwxr-xr-x', ) diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf b/src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf index c7a1730a..c7a1730a 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.conf diff --git a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml b/src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml index 033fbfaa..033fbfaa 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifcfg-rh.xml diff --git a/src/settings/plugins/ifcfg-rh/nm-ifdown b/src/core/settings/plugins/ifcfg-rh/nm-ifdown index e7bd73ae..e7bd73ae 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifdown +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifdown diff --git a/src/settings/plugins/ifcfg-rh/nm-ifup b/src/core/settings/plugins/ifcfg-rh/nm-ifup index 96637a92..96637a92 100644 --- a/src/settings/plugins/ifcfg-rh/nm-ifup +++ b/src/core/settings/plugins/ifcfg-rh/nm-ifup diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h index b986cc9a..79c67e48 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2013 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c index 5288f1bc..d114db0f 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Dan Williams <dcbw@redhat.com> * Søren Sandmann <sandmann@daimi.au.dk> * Copyright (C) 2007 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifcfg-rh-plugin.h" diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h index ff713cf3..dc1a01c8 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Dan Williams <dcbw@redhat.com> * Søren Sandmann <sandmann@daimi.au.dk> diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index 5a021a8c..209957d9 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifcfg-rh-reader.h" @@ -16,6 +16,7 @@ #include <sys/ioctl.h> #include <unistd.h> #include <linux/rtnetlink.h> +#include <linux/if_ether.h> #include "nm-glib-aux/nm-secret-utils.h" #include "nm-connection.h" @@ -39,7 +40,7 @@ #include "nm-setting-generic.h" #include "nm-core-internal.h" #include "nm-utils.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" +#include "nm-base/nm-ethtool-base.h" #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" @@ -2547,6 +2548,42 @@ make_ip6_setting(shvarFile *ifcfg, shvarFile *network_ifcfg, gboolean routes_rea } static NMSetting * +make_hostname_setting(shvarFile *ifcfg) +{ + NMSetting *setting; + NMTernary from_dhcp; + NMTernary from_dns_lookup; + NMTernary only_from_default; + int priority; + + priority = svGetValueInt64(ifcfg, "HOSTNAME_PRIORITY", 10, G_MININT32, G_MAXINT32, 0); + + from_dhcp = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DHCP"); + from_dns_lookup = svGetValueTernary(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP"); + only_from_default = svGetValueTernary(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT"); + + /* Create the setting when at least one key is not default*/ + if (priority == 0 && from_dhcp == NM_TERNARY_DEFAULT && from_dns_lookup == NM_TERNARY_DEFAULT + && only_from_default == NM_TERNARY_DEFAULT) + return NULL; + + setting = nm_setting_hostname_new(); + + g_object_set(setting, + NM_SETTING_HOSTNAME_PRIORITY, + priority, + NM_SETTING_HOSTNAME_FROM_DHCP, + from_dhcp, + NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP, + from_dns_lookup, + NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT, + only_from_default, + NULL); + + return setting; +} + +static NMSetting * make_sriov_setting(shvarFile *ifcfg) { gs_unref_hashtable GHashTable *keys = NULL; @@ -2951,7 +2988,8 @@ make_dcb_setting(shvarFile *ifcfg, NMSetting **out_setting, GError **error) gboolean dcb_on; NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE; - g_return_val_if_fail(out_setting != NULL, FALSE); + g_return_val_if_fail(out_setting, FALSE); + *out_setting = NULL; dcb_on = !!svGetValueBoolean(ifcfg, "DCB", FALSE); if (!dcb_on) @@ -3971,9 +4009,10 @@ make_wpa_setting(shvarFile * ifcfg, gs_unref_object NMSettingWirelessSecurity *wsec = NULL; gs_free char * value = NULL; const char * v; - gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_owe = FALSE, wpa_eap = FALSE, ieee8021x = FALSE; - int i_val; - GError * local = NULL; + gboolean wpa_psk = FALSE, wpa_sae = FALSE, wpa_owe = FALSE, wpa_eap = FALSE, ieee8021x = FALSE, + wpa3_eap = FALSE; + int i_val; + GError *local = NULL; wsec = NM_SETTING_WIRELESS_SECURITY(nm_setting_wireless_security_new()); @@ -3982,8 +4021,9 @@ make_wpa_setting(shvarFile * ifcfg, wpa_sae = nm_streq0(v, "SAE"); wpa_owe = nm_streq0(v, "OWE"); wpa_eap = nm_streq0(v, "WPA-EAP"); + wpa3_eap = nm_streq0(v, "WPA-EAP-SUITE-B-192"); ieee8021x = nm_streq0(v, "IEEE8021X"); - if (!wpa_psk && !wpa_sae && !wpa_owe && !wpa_eap && !ieee8021x) + if (!wpa_psk && !wpa_sae && !wpa_owe && !wpa_eap && !wpa3_eap && !ieee8021x) return NULL; /* Not WPA or Dynamic WEP */ /* WPS */ @@ -4046,7 +4086,7 @@ make_wpa_setting(shvarFile * ifcfg, g_object_set(wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "sae", NULL); } } else { - nm_assert(wpa_eap || ieee8021x || wpa_owe); + nm_assert(wpa_eap || wpa3_eap || ieee8021x || wpa_owe); /* Adhoc mode is mutually exclusive with any 802.1x-based authentication */ if (adhoc) { @@ -5339,24 +5379,31 @@ infiniband_connection_from_ifcfg(const char *file, shvarFile *ifcfg, GError **er static void handle_bond_option(NMSettingBond *s_bond, const char *key, const char *value) { - char * sanitized = NULL, *j; - const char *p = value; + gs_free char *sanitized = NULL; + const char * p = value; /* Remove any quotes or +/- from arp_ip_target */ - if (!g_strcmp0(key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) && value && value[0]) { + if (nm_streq0(key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET) && value && value[0]) { + char *j; + if (*p == '\'' || *p == '"') p++; - j = sanitized = g_malloc0(strlen(p) + 1); + j = sanitized = g_malloc(strlen(p) + 1); while (*p) { if (*p != '+' && *p != '-' && *p != '\'' && *p != '"') *j++ = *p; p++; } + *j++ = '\0'; + value = sanitized; } - if (!nm_setting_bond_add_option(s_bond, key, sanitized ?: value)) - PARSE_WARNING("invalid bonding option '%s' = %s", key, sanitized ?: value); - g_free(sanitized); + if (!_nm_setting_bond_validate_option(key, value, NULL)) { + PARSE_WARNING("invalid bonding option '%s' = %s", key, value); + return; + } + + nm_setting_bond_add_option(s_bond, key, value); } static NMSetting * @@ -6236,8 +6283,9 @@ connection_from_file_full(const char *filename, gs_unref_object NMConnection *connection = NULL; gs_free char * type = NULL; char * devtype, *bootproto; - NMSetting * s_ip4, *s_ip6, *s_tc, *s_proxy, *s_port, *s_dcb = NULL, *s_user; - NMSetting * s_sriov, *s_match; + NMSetting * setting; + NMSetting * s_ip4; + NMSetting * s_ip6; const char * ifcfg_name = NULL; gboolean has_ip4_defroute = FALSE; gboolean has_complex_routes_v4; @@ -6525,13 +6573,13 @@ connection_from_file_full(const char *filename, NM_SETTING_IP_CONFIG(s_ip4), NM_SETTING_IP_CONFIG(s_ip6)); - s_sriov = make_sriov_setting(main_ifcfg); - if (s_sriov) - nm_connection_add_setting(connection, s_sriov); + setting = make_sriov_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - s_tc = make_tc_setting(main_ifcfg); - if (s_tc) - nm_connection_add_setting(connection, s_tc); + setting = make_tc_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); /* For backwards compatibility, if IPv4 is disabled or the * config fails for some reason, we read DOMAIN and put the @@ -6539,30 +6587,34 @@ connection_from_file_full(const char *filename, */ check_dns_search_domains(main_ifcfg, s_ip4, s_ip6); - s_proxy = make_proxy_setting(main_ifcfg); - if (s_proxy) - nm_connection_add_setting(connection, s_proxy); + setting = make_proxy_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); + + setting = make_hostname_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - s_user = make_user_setting(main_ifcfg); - if (s_user) - nm_connection_add_setting(connection, s_user); + setting = make_user_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - s_match = make_match_setting(main_ifcfg); - if (s_match) - nm_connection_add_setting(connection, s_match); + setting = make_match_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - s_port = make_bridge_port_setting(main_ifcfg); - if (s_port) - nm_connection_add_setting(connection, s_port); + setting = make_bridge_port_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - s_port = make_team_port_setting(main_ifcfg); - if (s_port) - nm_connection_add_setting(connection, s_port); + setting = make_team_port_setting(main_ifcfg); + if (setting) + nm_connection_add_setting(connection, setting); - if (!make_dcb_setting(main_ifcfg, &s_dcb, error)) + if (!make_dcb_setting(main_ifcfg, &setting, error)) return NULL; - if (s_dcb) - nm_connection_add_setting(connection, s_dcb); + if (setting) + nm_connection_add_setting(connection, setting); if (!nm_connection_normalize(connection, NULL, NULL, error)) return NULL; diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h index 7bbb6d80..c7dc2240 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c index 28ec893f..3f674dea 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifcfg-rh-storage.h" diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h index b8787def..6fb9838f 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-storage.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 567dc8a8..8da5de47 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifcfg-rh-utils.h" @@ -544,6 +544,7 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME(NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_LRO, "lro"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_MACSEC_HW_OFFLOAD, "macsec-hw-offload"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_NTUPLE, "ntuple"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX, "rx"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RXHASH, "rxhash"), @@ -551,12 +552,15 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_GRO_LIST, "rx-gro-list"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_UDP_GRO_FORWARDING, "rx-udp-gro-forwarding"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_SG, "sg"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TLS_HW_RX_OFFLOAD, "tls-hw-rx-offload"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TSO, "tso"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX, "tx"), @@ -570,6 +574,7 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_GSO_LIST, "tx-gso-list"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), @@ -582,6 +587,8 @@ const char *const _nm_ethtool_ifcfg_names[] = { ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), + ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_TUNNEL_REMCSUM_SEGMENTATION, + "tx-tunnel-remcsum-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), ETHT_NAME(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), @@ -648,6 +655,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"l2-fwd-offload", NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD}, {"loopback", NM_ETHTOOL_ID_FEATURE_LOOPBACK}, {"lro", NM_ETHTOOL_ID_FEATURE_LRO}, + {"macsec-hw-offload", NM_ETHTOOL_ID_FEATURE_MACSEC_HW_OFFLOAD}, {"ntuple", NM_ETHTOOL_ID_FEATURE_NTUPLE}, {"rx", NM_ETHTOOL_ID_FEATURE_RX}, {"rx-all", NM_ETHTOOL_ID_FEATURE_RX_ALL}, @@ -655,9 +663,11 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"rx-fcs", NM_ETHTOOL_ID_FEATURE_RX_FCS}, {"rx-gro", NM_ETHTOOL_ID_FEATURE_GRO}, // kernel-only name {"rx-gro-hw", NM_ETHTOOL_ID_FEATURE_RX_GRO_HW}, + {"rx-gro-list", NM_ETHTOOL_ID_FEATURE_RX_GRO_LIST}, {"rx-hashing", NM_ETHTOOL_ID_FEATURE_RXHASH}, // kernel-only name {"rx-lro", NM_ETHTOOL_ID_FEATURE_LRO}, // kernel-only name {"rx-ntuple-filter", NM_ETHTOOL_ID_FEATURE_NTUPLE}, // kernel-only name + {"rx-udp-gro-forwarding", NM_ETHTOOL_ID_FEATURE_RX_UDP_GRO_FORWARDING}, {"rx-udp_tunnel-port-offload", NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD}, {"rx-vlan-filter", NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER}, {"rx-vlan-hw-parse", NM_ETHTOOL_ID_FEATURE_RXVLAN}, // kernel-only name @@ -667,6 +677,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"rxvlan", NM_ETHTOOL_ID_FEATURE_RXVLAN}, {"sg", NM_ETHTOOL_ID_FEATURE_SG}, {"tls-hw-record", NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD}, + {"tls-hw-rx-offload", NM_ETHTOOL_ID_FEATURE_TLS_HW_RX_OFFLOAD}, {"tls-hw-tx-offload", NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD}, {"tso", NM_ETHTOOL_ID_FEATURE_TSO}, {"tx", NM_ETHTOOL_ID_FEATURE_TX}, @@ -680,6 +691,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"tx-generic-segmentation", NM_ETHTOOL_ID_FEATURE_GSO}, // kernel-only name {"tx-gre-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION}, {"tx-gre-segmentation", NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION}, + {"tx-gso-list", NM_ETHTOOL_ID_FEATURE_TX_GSO_LIST}, {"tx-gso-partial", NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL}, {"tx-gso-robust", NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST}, {"tx-ipxip4-segmentation", NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION}, @@ -692,6 +704,7 @@ static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE( {"tx-tcp-mangleid-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION}, {"tx-tcp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION}, {"tx-tcp6-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION}, + {"tx-tunnel-remcsum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_TUNNEL_REMCSUM_SEGMENTATION}, {"tx-udp-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION}, {"tx-udp_tnl-csum-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION}, {"tx-udp_tnl-segmentation", NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION}, @@ -873,6 +886,10 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("GATEWAY_PING_TIMEOUT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("GENERATE_MAC_ADDRESS_MASK", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("GVRP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("HOSTNAME_FROM_DHCP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("HOSTNAME_FROM_DNS_LOOKUP", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("HOSTNAME_ONLY_FROM_DEFAULT", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("HOSTNAME_PRIORITY", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("HWADDR", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("HWADDR_BLACKLIST", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("IEEE_8021X_ALTSUBJECT_MATCHES", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 16ea7f0f..36ec9225 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2017 Red Hat, Inc. */ @@ -7,7 +7,7 @@ #define _UTILS_H_ #include "nm-connection.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" +#include "nm-base/nm-ethtool-base.h" #include "shvar.h" @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[243]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[247]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 64884672..a968fce0 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifcfg-rh-writer.h" @@ -34,8 +34,7 @@ #include "nm-utils.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "nm-meta-setting.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" +#include "nm-base/nm-ethtool-base.h" #include "nms-ifcfg-rh-common.h" #include "nms-ifcfg-rh-reader.h" @@ -614,6 +613,9 @@ write_wireless_security_setting(NMConnection *connection, } else if (!strcmp(key_mgmt, "wpa-eap")) { svSetValueStr(ifcfg, "KEY_MGMT", "WPA-EAP"); wpa = TRUE; + } else if (!strcmp(key_mgmt, "wpa-eap-suite-b-192")) { + svSetValueStr(ifcfg, "KEY_MGMT", "WPA-EAP-SUITE-B-192"); + wpa = TRUE; } if (auth_alg) { @@ -1051,6 +1053,28 @@ write_infiniband_setting(NMConnection *connection, shvarFile *ifcfg, GError **er return TRUE; } +static void +write_hostname_setting(NMConnection *connection, shvarFile *ifcfg) +{ + NMSettingHostname *s_hostname; + NMTernary t; + + s_hostname = _nm_connection_get_setting(connection, NM_TYPE_SETTING_HOSTNAME); + if (!s_hostname) + return; + + svSetValueInt64(ifcfg, "HOSTNAME_PRIORITY", nm_setting_hostname_get_priority(s_hostname)); + + t = nm_setting_hostname_get_from_dhcp(s_hostname); + svSetValueInt64_cond(ifcfg, "HOSTNAME_FROM_DHCP", t != NM_TERNARY_DEFAULT, t); + + t = nm_setting_hostname_get_from_dns_lookup(s_hostname); + svSetValueInt64_cond(ifcfg, "HOSTNAME_FROM_DNS_LOOKUP", t != NM_TERNARY_DEFAULT, t); + + t = nm_setting_hostname_get_only_from_default(s_hostname); + svSetValueInt64_cond(ifcfg, "HOSTNAME_ONLY_FROM_DEFAULT", t != NM_TERNARY_DEFAULT, t); +} + static gboolean write_wired_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) { @@ -3347,7 +3371,7 @@ do_write_construct(NMConnection * connection, return FALSE; write_match_setting(connection, ifcfg); - + write_hostname_setting(connection, ifcfg); write_sriov_setting(connection, ifcfg); if (!write_tc_setting(connection, ifcfg, error)) diff --git a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h index 1c58a346..d0d8a4cd 100644 --- a/src/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2009 Red Hat, Inc. */ diff --git a/src/settings/plugins/ifcfg-rh/shvar.c b/src/core/settings/plugins/ifcfg-rh/shvar.c index 8f5be2cc..386bcac7 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.c +++ b/src/core/settings/plugins/ifcfg-rh/shvar.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 1999, 2000 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "shvar.h" diff --git a/src/settings/plugins/ifcfg-rh/shvar.h b/src/core/settings/plugins/ifcfg-rh/shvar.h index 60324be0..6965d873 100644 --- a/src/settings/plugins/ifcfg-rh/shvar.h +++ b/src/core/settings/plugins/ifcfg-rh/shvar.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 1999 Red Hat, Inc. */ diff --git a/src/core/settings/plugins/ifcfg-rh/tests/meson.build b/src/core/settings/plugins/ifcfg-rh/tests/meson.build new file mode 100644 index 00000000..077e4782 --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/meson.build @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +exe = executable( + 'test-ifcfg-rh', + 'test-ifcfg-rh.c', + dependencies: libNetworkManagerTest_dep, + c_args: test_c_flags, + link_with: libnms_ifcfg_rh_core, +) + +test( + 'ifcfg-rh/test-ifcfg-rh', + test_script, + timeout: 90, + args: test_args + [exe.full_path()], +) diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected index d81d9187..d81d9187 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-a.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected index 2e69c5e7..2e69c5e7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-bridge-component-b.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected index 59a6f79b..59a6f79b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-System_test-wired-802-1X-subj-matches.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected index a48be78a..a48be78a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_User_1.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected index b288c04a..b288c04a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bond_Main.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected index a8ff8df3..a8ff8df3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Bridge_Component.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected index 80e96921..80e96921 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Permissions.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected index 716eedc2..716eedc2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Proxy_Basic.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected index 0c2fa035..0c2fa035 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Routing_Rules.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected index 2df1fbb3..2df1fbb3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Infiniband_Port.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected index ff55cefe..ff55cefe 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Team_Port.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected index 9c2a1ff0..9c2a1ff0 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_VLAN_reorder_hdr.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected index ccec2b81..ccec2b81 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_AP_Mode.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected index ddbd986f..ddbd986f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Band_A.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected index 495a24d3..495a24d3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_Hidden.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected index aec6918a..aec6918a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_always.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected index 9d47163f..9d47163f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_default.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected index 43c07ddb..43c07ddb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_missing.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected index 21f2e2de..21f2e2de 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_WiFi_MAC_never.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected index d3db19b2..d3db19b2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_LEAP.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected index 32db7262..32db7262 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wifi_WEP_104_ASCII.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected index 214f5da5..214f5da5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Auto-Negotiate.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected index cd8fc96f..cd8fc96f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Static_Routes.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected index de66dcdd..de66dcdd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_Wake-on-LAN.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected index 9499278e..9499278e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Test_Write_Wired_match.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected index 44eb777c..44eb777c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-Vlan_test-vlan-interface.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 index 4f9d645c..4f9d645c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 index 37c0df11..37c0df11 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 index 0c3b6a7e..0c3b6a7e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 index 5df3f154..5df3f154 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem0:99 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 index f6fefc0d..f6fefc0d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 index 21971611..21971611 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem1:1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 index 92ed461e..92ed461e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 index ce0f23ba..ce0f23ba 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem2:1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 index b7bdd781..b7bdd781 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 index 5e151875..5e151875 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-aliasem3:1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected index 56e233cc..56e233cc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-dcb-test.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 index ecb36c37..ecb36c37 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected index 87493ac2..87493ac2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-netmask-1.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected index ead3a047..ead3a047 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected index 7bc1ae6c..7bc1ae6c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-random_wifi_connection_2.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected index b01372af..b01372af 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-team-slave-enp31s0f1-142.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type index 8d295c76..8d295c76 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-eth-type diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main index 4c4834d5..4c4834d5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-main diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric index 9989f58b..9989f58b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-mode-numeric diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave index c0de645d..c0de645d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib index 5bd9a3a8..5bd9a3a8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bond-slave-ib diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component index 24b51221..24b51221 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-component diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main index 1788efe2..1788efe2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-main diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp index 7135cd42..7135cd42 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-bridge-missing-stp diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb index 6e6589d3..6e6589d3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans index 2f46a082..2f46a082 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-booleans diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent index 0c5d7b88..0c5d7b88 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-percent diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints index 8334999b..8334999b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-bad-uints diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities index 5bdcb63c..5bdcb63c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-default-app-priorities diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 index 95eb7c5b..95eb7c5b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-pgpct-not-100 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans index fbe1cbbc..fbe1cbbc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-booleans diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent index 07ba6b64..07ba6b64 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-percent diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints index 05ae39cb..05ae39cb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dcb-short-uints diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options index cea2471a..cea2471a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-dns-options diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric index cde1c28d..cde1c28d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-fabric diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn index 20c08451..20c08451 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-fcoe-vn2vn diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft index d3e4edca..d3e4edca 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ibft diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband index 6c36f1de..6c36f1de 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected index cae51b89..cae51b89 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-ip6-disabled.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal index 63bcc840..63bcc840 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-minimal diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables index 1b10cddb..1b10cddb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-misc-variables diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled index a38f1f5f..a38f1f5f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized index 58263ece..58263ece 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-nm-controlled-unrecognized diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip index b5028daa..b5028daa 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-noip diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no index b9491711..b9491711 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-onboot-no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions index 5b413aa9..5b413aa9 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-permissions diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic index e2cf6c21..e2cf6c21 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-read-proxy-basic diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore index a2581db6..a2581db6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sit-ignore diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov index 142f56e4..142f56e4 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected index c882c479..c882c479 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-sriov-write.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy index 2173729d..2173729d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected index a28c5c1c..a28c5c1c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc index d0a3c254..d0a3c254 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected index a67ca598..a67ca598 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-tc-write.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 index 209447b8..209447b8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 index 26e448cc..26e448cc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid index 41c0f25c..41c0f25c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-master-invalid diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 index 80355c26..80355c26 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 index 4284737a..4284737a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config index 04df6938..04df6938 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-team-port-empty-config diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized index 18da66c1..18da66c1 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-unrecognized diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1 index af62dcfc..af62dcfc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-variables-corner-cases-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1 index 5ff87891..5ff87891 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 index 2c01be71..2c01be71 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-flags-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface index d8d9193f..d8d9193f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-interface diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device index 4ba06f28..4ba06f28 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-device diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid index 622d41ec..622d41ec 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-only-vlanid diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev index 446c2a62..446c2a62 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-physdev diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 index 0dc53971..0dc53971 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 index d98a9d36..d98a9d36 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-reorder-hdr-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces index 4a31e475..4a31e475 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-vlan-trailing-spaces diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a index 43286111..43286111 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch index 8905ba0b..8905ba0b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-a-channel-mismatch diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch index e02e21ad..e02e21ad 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-band-bg-channel-mismatch diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap index d9c95cc2..d9c95cc2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-dynamic-wep-leap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden index 08b9a730..08b9a730 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-hidden diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap index 50f4fd31..50f4fd31 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent index 991ba67a..991ba67a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-agent diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask index 5bb02b5c..5bb02b5c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-leap-always-ask diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always index 9dcb5bf8..9dcb5bf8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-always diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default index 3709c493..3709c493 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-default diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing index f896eb0f..f896eb0f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-missing diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never index aa12d749..aa12d749 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-mac-random-never diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open index b089103d..b089103d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto index 42ee200a..42ee200a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex index 32d63342..32d63342 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex index dcb46da7..dcb46da7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-hex diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex index 37bb085b..37bb085b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-hex diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted index 0b46acd6..0b46acd6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted index 08496bb5..08496bb5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-ssid-quoted diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe index 354046ad..354046ad 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-owe diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae index 68afbe97..68afbe97 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-sae diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep index e1ce20d6..e1ce20d6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii index 250efa13..250efa13 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-104-ascii diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii index 250efa13..250efa13 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-40-ascii diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc index 9d0bacfc..9d0bacfc 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-adhoc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys index 2bc16b6e..2bc16b6e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-agent-keys diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap index bdea6aa3..bdea6aa3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-eap-ttls-chap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys index cb4da43f..cb4da43f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-no-keys diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase index 250efa13..250efa13 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wep-passphrase diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls new file mode 100644 index 00000000..9a74bb4d --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-suite-b-192-tls @@ -0,0 +1,22 @@ +TYPE=Wireless +DEVICE=eth2 +HWADDR=00:16:41:11:22:33 +BOOTPROTO=dhcp +ONBOOT=yes +ONBOOT=yes +USERCTL=yes +IPV6INIT=no +NM_CONTROLLED=yes +PEERDNS=yes +ESSID=blahblah +MODE=Managed +RATE=auto +KEY_MGMT=WPA-EAP-SUITE-B-192 +WPA_ALLOW_WPA=yes +WPA_ALLOW_WPA2=yes +IEEE_8021X_EAP_METHODS=TLS +IEEE_8021X_IDENTITY="Bill Smith" +IEEE_8021X_CA_CERT=test_ca_cert.pem +IEEE_8021X_CLIENT_CERT=test1_key_and_cert.pem +IEEE_8021X_PRIVATE_KEY=test1_key_and_cert.pem + diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls index 92aaeeab..92aaeeab 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-tls diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls index 42ed1d68..42ed1d68 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-eap-ttls-tls diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk index 4ab45ae3..4ab45ae3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 index 038b656d..038b656d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc index c3cadbb8..c3cadbb8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-adhoc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex index 2119ba8e..2119ba8e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-hex diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted index 2119ba8e..2119ba8e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2 index 2119ba8e..2119ba8e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-wpa-psk-unquoted2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches index 70d69bf5..70d69bf5 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1X-subj-matches diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw index a5434434..a5434434 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-password-raw diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc index fad92772..fad92772 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-802-1x-ttls-eapgtc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 index 27bcbbf9..27bcbbf9 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-peap-mschapv2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent index 052ab425..052ab425 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-agent diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always index 5deee066..5deee066 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-always diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert index 24397473..24397473 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-8021x-tls-p12-no-client-cert diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on index d0b50775..d0b50775 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-auto-negotiate-on diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip index e683db3c..e683db3c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-autoip diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static index 61f8f423..61f8f423 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ctc-static diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no index fe8b15b2..fe8b15b2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes index 3cf4323d..3cf4323d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-defroute-no-gatewaydev-yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp index 5d36675a..5d36675a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip index af254f9c..af254f9c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-plus-ip diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname index cba380db..cba380db 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp-send-hostname diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only index de03e044..de03e044 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcp6-only diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback index d38e762e..d38e762e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-dhcpv6-hostname-fallback diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway index 98d91053..98d91053 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore index bb81399e..bb81399e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-global-gateway-ignore diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1 index db09afdb..db09afdb 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2 index 6972e279..6972e279 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3 index d9065994..d9065994 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-3 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4 index 935267f7..935267f7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv4-manual-4 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual index 45db0e4c..45db0e4c 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-manual diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only index 94189064..94189064 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 index 95f8a8ed..95f8a8ed 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-ipv6-only-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default index 12d5b5e6..12d5b5e6 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-never-default diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n index 2190a995..2190a995 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-obsolete-gateway-n diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static index 4719de21..4719de21 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-qeth-static diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip index 5098aef7..5098aef7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-shared-plus-ip diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static index 34acf9fe..34acf9fe 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto index a01f6558..a01f6558 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-bootproto diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16 index 07999038..07999038 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-16 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24 index 688143cd..688143cd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-24 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8 index 0433c62a..0433c62a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-no-prefix-8 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes index 7faf49bd..7faf49bd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy index 7faf49bd..7faf49bd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt index 861dd41f..861dd41f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-unknown-ethtool-opt diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan index 1dfc9a43..1dfc9a43 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-wake-on-lan diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1 index 2af1daf3..2af1daf3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected index 7f154073..7f154073 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-1.expected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2 index 850149b2..850149b2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected index 6ec53c17..6ec53c17 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-2.expected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3 index 3d198e00..3d198e00 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected index d2b27eb3..d2b27eb3 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-3.expected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 index f834464e..f834464e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected index 040ddc9d..040ddc9d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-write-unknown-4.expected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected index 42608576..42608576 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test_write_wired_auto_negotiate_on.cexpected diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap index 6936f2e0..6936f2e0 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-dynamic-wep-leap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap index fe78177e..fe78177e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-leap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae index 5a9569ed..5a9569ed 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-sae diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep index 0bd766c2..0bd766c2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii index f5d532b2..f5d532b2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-104-ascii diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii index b0d14708..b0d14708 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-40-ascii diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc index 0bd766c2..0bd766c2 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-adhoc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap index 6936f2e0..6936f2e0 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-eap-ttls-chap diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase index d45c0ea8..d45c0ea8 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wep-passphrase diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls index 0c3bc1e1..0c3bc1e1 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-tls diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls index b6256b95..b6256b95 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-eap-ttls-tls diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk index d7813b2f..d7813b2f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 index 995721dd..995721dd 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc index d7813b2f..d7813b2f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-adhoc diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex index d0576a8d..d0576a8d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-hex diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted index 9a47196a..9a47196a 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2 index 347bb85e..347bb85e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-unquoted2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw index d29a4289..d29a4289 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-802-1x-password-raw diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 index 6936f2e0..6936f2e0 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wired-8021x-peap-mschapv2 diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes index 0d6a302f..0d6a302f 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-defroute-no-gatewaydev-yes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway index 7987d105..7987d105 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore index 7987d105..7987d105 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-global-gateway-ignore diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default index 4347405e..4347405e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/network-test-wired-never-default diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy index c9e422e7..c9e422e7 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes index 9c05417e..9c05417e 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy index 1fef7e97..1fef7e97 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual index 8bdf0acf..8bdf0acf 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/route6-test-wired-ipv6-manual diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem index dec9aa1b..dec9aa1b 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test1_key_and_cert.pem diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem index ef1be20d..ef1be20d 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_ca_cert.pem diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 index edc2af75..edc2af75 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/test_client.p12 Binary files differdiff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index a4e9d804..59127d01 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> @@ -14,6 +14,8 @@ #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> +#include <linux/if_ether.h> +#include <linux/if_infiniband.h> #include "nm-glib-aux/nm-json-aux.h" #include "nm-utils.h" @@ -35,7 +37,8 @@ #include "nm-setting-vlan.h" #include "nm-setting-dcb.h" #include "nm-core-internal.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" +#include "nm-base/nm-ethtool-base.h" +#include "nm-base/nm-ethtool-utils-base.h" #include "NetworkManagerUtils.h" @@ -46,8 +49,9 @@ #include "nm-test-utils-core.h" -#define TEST_IFCFG_DIR NM_BUILD_SRCDIR "/src/settings/plugins/ifcfg-rh/tests/network-scripts" -#define TEST_SCRATCH_DIR NM_BUILD_BUILDDIR "/src/settings/plugins/ifcfg-rh/tests/network-scripts" +#define TEST_IFCFG_DIR NM_BUILD_SRCDIR "/src/core/settings/plugins/ifcfg-rh/tests/network-scripts" +#define TEST_SCRATCH_DIR \ + NM_BUILD_BUILDDIR "/src/core/settings/plugins/ifcfg-rh/tests/network-scripts" #define TEST_SCRATCH_DIR_TMP TEST_SCRATCH_DIR "/tmp" #define TEST_SCRATCH_ALIAS_BASE TEST_SCRATCH_DIR "/ifcfg-alias0" @@ -3685,6 +3689,34 @@ test_read_wifi_wpa_eap_ttls_tls(void) } static void +test_read_wifi_wpa_eap_suite_b_192_tls(void) +{ + NMConnection * connection; + NMSettingWireless * s_wireless; + NMSettingWirelessSecurity *s_wireless_sec; + + connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-wifi-wpa-eap-suite-b-192-tls", + NULL, + TYPE_WIRELESS, + NULL); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = nm_connection_get_setting_wireless(connection); + g_assert(s_wireless); + + /* ===== WIRELESS SECURITY SETTING ===== */ + + s_wireless_sec = nm_connection_get_setting_wireless_security(connection); + g_assert(s_wireless_sec); + g_assert_cmpstr(nm_setting_wireless_security_get_key_mgmt(s_wireless_sec), + ==, + "wpa-eap-suite-b-192"); + + g_object_unref(connection); +} + +static void test_read_wifi_dynamic_wep_leap(void) { NMConnection * connection; @@ -11535,6 +11567,8 @@ main(int argc, char **argv) g_test_add_func(TPATH "wifi/read/dynamic-wep/leap", test_read_wifi_dynamic_wep_leap); g_test_add_func(TPATH "wifi/read/wpa/eap/tls", test_read_wifi_wpa_eap_tls); g_test_add_func(TPATH "wifi/read/wpa/eap/ttls/tls", test_read_wifi_wpa_eap_ttls_tls); + g_test_add_func(TPATH "wifi/read/wpa/eap-suite-b-192/tls", + test_read_wifi_wpa_eap_suite_b_192_tls); g_test_add_func(TPATH "wifi/read/dynamic-wep/eap/ttls/chap", test_read_wifi_wep_eap_ttls_chap); g_test_add_func(TPATH "wifi/read-band-a", test_read_wifi_band_a); g_test_add_func(TPATH "wifi/read-band-a-channel-mismatch", diff --git a/src/settings/plugins/ifupdown/meson.build b/src/core/settings/plugins/ifupdown/meson.build index 7e2b44fb..dd252783 100644 --- a/src/settings/plugins/ifupdown/meson.build +++ b/src/core/settings/plugins/ifupdown/meson.build @@ -1,21 +1,19 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nms-ifupdown-interface-parser.c', - 'nms-ifupdown-parser.c', -) +# SPDX-License-Identifier: LGPL-2.1-or-later libnms_ifupdown_core = static_library( 'nms-ifupdown-core', - sources: sources, - dependencies: daemon_nm_default_dep, + sources: files( + 'nms-ifupdown-interface-parser.c', + 'nms-ifupdown-parser.c', + ), + dependencies: core_default_dep, c_args: daemon_c_flags, ) libnm_settings_plugin_ifupdown = shared_module( 'nm-settings-plugin-ifupdown', sources: 'nms-ifupdown-plugin.c', - dependencies: daemon_nm_default_dep, + dependencies: core_plugin_dep, c_args: daemon_c_flags, link_with: libnms_ifupdown_core, link_args: ldflags_linker_script_settings, diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c index 219490b8..a8a9c40a 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Tom Parker <palfrey@tevp.net> * Copyright (C) 2004 Tom Parker */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifupdown-interface-parser.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h index d8256a5b..dd0e15fb 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-interface-parser.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Tom Parker <palfrey@tevp.net> * Copyright (C) 2004 Tom Parker diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c index 0e01d6c5..a4974a96 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Alexander Sack <asac@ubuntu.com> * Copyright (C) 2008 Canonical Ltd. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifupdown-parser.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.h index c5fc2874..ced98dba 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-parser.h +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-parser.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Alexander Sack <asac@ubuntu.com> * Copyright (C) 2008 Canonical Ltd. diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c index b6ba423c..34523f8d 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.c +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.c @@ -1,11 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Alexander Sack <asac@ubuntu.com> * Copyright (C) 2007, 2008 Canonical Ltd. * Copyright (C) 2009 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-ifupdown-plugin.h" diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.h index a3b73ea1..edf1b317 100644 --- a/src/settings/plugins/ifupdown/nms-ifupdown-plugin.h +++ b/src/core/settings/plugins/ifupdown/nms-ifupdown-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Alexander Sack <asac@ubuntu.com> * Copyright (C) 2008 Canonical Ltd. diff --git a/src/core/settings/plugins/ifupdown/tests/meson.build b/src/core/settings/plugins/ifupdown/tests/meson.build new file mode 100644 index 00000000..882287cb --- /dev/null +++ b/src/core/settings/plugins/ifupdown/tests/meson.build @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +exe = executable( + 'test-ifupdown', + 'test-ifupdown.c', + dependencies: libNetworkManagerTest_dep, + c_args: test_c_flags, + link_with: libnms_ifupdown_core, +) + +test( + 'ifupdown/test-ifupdown', + test_script, + args: test_args + [exe.full_path()], +) diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c index d2d8558e..6e3eb0e7 100644 --- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c +++ b/src/core/settings/plugins/ifupdown/tests/test-ifupdown.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-core-internal.h" @@ -12,7 +12,7 @@ #include "nm-test-utils-core.h" -#define TEST_DIR NM_BUILD_SRCDIR "/src/settings/plugins/ifupdown/tests" +#define TEST_DIR NM_BUILD_SRCDIR "/src/core/settings/plugins/ifupdown/tests" /*****************************************************************************/ diff --git a/src/settings/plugins/ifupdown/tests/test1 b/src/core/settings/plugins/ifupdown/tests/test1 index 74c23b45..74c23b45 100644 --- a/src/settings/plugins/ifupdown/tests/test1 +++ b/src/core/settings/plugins/ifupdown/tests/test1 diff --git a/src/settings/plugins/ifupdown/tests/test11 b/src/core/settings/plugins/ifupdown/tests/test11 index 89561dd7..89561dd7 100644 --- a/src/settings/plugins/ifupdown/tests/test11 +++ b/src/core/settings/plugins/ifupdown/tests/test11 diff --git a/src/settings/plugins/ifupdown/tests/test12 b/src/core/settings/plugins/ifupdown/tests/test12 index 6096842e..6096842e 100644 --- a/src/settings/plugins/ifupdown/tests/test12 +++ b/src/core/settings/plugins/ifupdown/tests/test12 diff --git a/src/settings/plugins/ifupdown/tests/test13 b/src/core/settings/plugins/ifupdown/tests/test13 index c001f7ef..c001f7ef 100644 --- a/src/settings/plugins/ifupdown/tests/test13 +++ b/src/core/settings/plugins/ifupdown/tests/test13 diff --git a/src/settings/plugins/ifupdown/tests/test14 b/src/core/settings/plugins/ifupdown/tests/test14 index 4a153ab3..4a153ab3 100644 --- a/src/settings/plugins/ifupdown/tests/test14 +++ b/src/core/settings/plugins/ifupdown/tests/test14 diff --git a/src/settings/plugins/ifupdown/tests/test15 b/src/core/settings/plugins/ifupdown/tests/test15 index c3ceca24..c3ceca24 100644 --- a/src/settings/plugins/ifupdown/tests/test15 +++ b/src/core/settings/plugins/ifupdown/tests/test15 diff --git a/src/settings/plugins/ifupdown/tests/test16 b/src/core/settings/plugins/ifupdown/tests/test16 index f4f74fb5..f4f74fb5 100644 --- a/src/settings/plugins/ifupdown/tests/test16 +++ b/src/core/settings/plugins/ifupdown/tests/test16 diff --git a/src/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4 b/src/core/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4 index 9e5243a7..9e5243a7 100644 --- a/src/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4 +++ b/src/core/settings/plugins/ifupdown/tests/test17-wired-static-verify-ip4 diff --git a/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 b/src/core/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 index 29546a61..29546a61 100644 --- a/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 +++ b/src/core/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 diff --git a/src/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen b/src/core/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen index 441106da..441106da 100644 --- a/src/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen +++ b/src/core/settings/plugins/ifupdown/tests/test19-wired-static-verify-ip4-plen diff --git a/src/settings/plugins/ifupdown/tests/test2 b/src/core/settings/plugins/ifupdown/tests/test2 index 7462b352..7462b352 100644 --- a/src/settings/plugins/ifupdown/tests/test2 +++ b/src/core/settings/plugins/ifupdown/tests/test2 diff --git a/src/settings/plugins/ifupdown/tests/test20-source-stanza b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza index 5cfe1730..5cfe1730 100644 --- a/src/settings/plugins/ifupdown/tests/test20-source-stanza +++ b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza diff --git a/src/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 index 81922cea..81922cea 100644 --- a/src/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 +++ b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth0 diff --git a/src/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 index b8a783f5..b8a783f5 100644 --- a/src/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 +++ b/src/core/settings/plugins/ifupdown/tests/test20-source-stanza.eth1 diff --git a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza b/src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza index d0604ddc..d0604ddc 100644 --- a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza +++ b/src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza diff --git a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 b/src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 index 81922cea..81922cea 100644 --- a/src/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 +++ b/src/core/settings/plugins/ifupdown/tests/test21-source-dir-stanza.d/test21-source-dir-stanza.eth0 diff --git a/src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas b/src/core/settings/plugins/ifupdown/tests/test22-duplicate-stanzas index c13c2e7e..c13c2e7e 100644 --- a/src/settings/plugins/ifupdown/tests/test22-duplicate-stanzas +++ b/src/core/settings/plugins/ifupdown/tests/test22-duplicate-stanzas diff --git a/src/settings/plugins/ifupdown/tests/test3 b/src/core/settings/plugins/ifupdown/tests/test3 index f6293bbd..f6293bbd 100644 --- a/src/settings/plugins/ifupdown/tests/test3 +++ b/src/core/settings/plugins/ifupdown/tests/test3 diff --git a/src/settings/plugins/ifupdown/tests/test4 b/src/core/settings/plugins/ifupdown/tests/test4 index 46a40bc9..46a40bc9 100644 --- a/src/settings/plugins/ifupdown/tests/test4 +++ b/src/core/settings/plugins/ifupdown/tests/test4 diff --git a/src/settings/plugins/ifupdown/tests/test5 b/src/core/settings/plugins/ifupdown/tests/test5 index b69fc42b..b69fc42b 100644 --- a/src/settings/plugins/ifupdown/tests/test5 +++ b/src/core/settings/plugins/ifupdown/tests/test5 diff --git a/src/settings/plugins/ifupdown/tests/test6 b/src/core/settings/plugins/ifupdown/tests/test6 index 50ac69bd..50ac69bd 100644 --- a/src/settings/plugins/ifupdown/tests/test6 +++ b/src/core/settings/plugins/ifupdown/tests/test6 diff --git a/src/settings/plugins/ifupdown/tests/test7 b/src/core/settings/plugins/ifupdown/tests/test7 index 03cb131a..03cb131a 100644 --- a/src/settings/plugins/ifupdown/tests/test7 +++ b/src/core/settings/plugins/ifupdown/tests/test7 diff --git a/src/settings/plugins/ifupdown/tests/test8 b/src/core/settings/plugins/ifupdown/tests/test8 index 311f7e15..311f7e15 100644 --- a/src/settings/plugins/ifupdown/tests/test8 +++ b/src/core/settings/plugins/ifupdown/tests/test8 diff --git a/src/settings/plugins/ifupdown/tests/test9 b/src/core/settings/plugins/ifupdown/tests/test9 index 7d94563a..7d94563a 100644 --- a/src/settings/plugins/ifupdown/tests/test9 +++ b/src/core/settings/plugins/ifupdown/tests/test9 diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c index 48cb8caa..789bfc1a 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-keyfile-plugin.h" @@ -23,7 +23,7 @@ #include "nm-utils.h" #include "nm-config.h" #include "nm-core-internal.h" -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "systemd/nm-sd-utils-shared.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.h b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.h index b52fe9db..5d9f2da3 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-plugin.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-plugin.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2011 Red Hat, Inc. diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c index 669f22fd..70b047f3 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-reader.c @@ -1,15 +1,15 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-keyfile-reader.h" #include <sys/stat.h> -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "NetworkManagerUtils.h" #include "nms-keyfile-utils.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/core/settings/plugins/keyfile/nms-keyfile-reader.h index e7853cc6..247457d8 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-reader.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-reader.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 Red Hat, Inc. diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.c b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c index 9cd62780..89be817a 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-storage.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-storage.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-keyfile-storage.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.h b/src/core/settings/plugins/keyfile/nms-keyfile-storage.h index 90ff6f35..008070df 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-storage.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-storage.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c index 851e7815..f3dffdae 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-keyfile-utils.h" @@ -11,7 +11,7 @@ #include <sys/stat.h> #include "nm-glib-aux/nm-io-utils.h" -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "nm-utils.h" #include "nm-setting-wired.h" #include "nm-setting-wireless.h" diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/core/settings/plugins/keyfile/nms-keyfile-utils.h index 4b5b4bb5..419a17ed 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-utils.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-utils.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 - 2018 Red Hat, Inc. */ diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c index 4b13cef4..0e2c94b5 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nms-keyfile-writer.h" @@ -12,7 +12,7 @@ #include <sys/stat.h> #include <unistd.h> -#include "nm-keyfile/nm-keyfile-internal.h" +#include "nm-keyfile-internal.h" #include "nms-keyfile-utils.h" #include "nms-keyfile-reader.h" @@ -323,12 +323,20 @@ _internal_write_connection(NMConnection * connection, } if (!path) { + gs_free char *ss = NULL; + /* this really should not happen, we tried hard to find an unused name... bail out. */ g_set_error(error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, "could not find suitable keyfile file name (%s already used)", - path); + ss = ({ + gs_free char *filename_escaped = NULL; + + filename_escaped = nm_keyfile_utils_create_filename(id, with_extension); + g_build_filename(keyfile_dir, filename_escaped, NULL); + })); + return FALSE; } diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/core/settings/plugins/keyfile/nms-keyfile-writer.h index 07de6569..dffd3b04 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.h +++ b/src/core/settings/plugins/keyfile/nms-keyfile-writer.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 Novell, Inc. * Copyright (C) 2008 - 2011 Red Hat, Inc. diff --git a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT b/src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT index 162bf72e..162bf72e 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_BT diff --git a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain b/src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain index 11e1ec6f..11e1ec6f 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/ATT_Data_Connect_Plain diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component index f5463ed0..f5463ed0 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Component diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main index fc9fd8f8..fc9fd8f8 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Bridge_Main diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property index 52b395b3..52b395b3 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Enum_Property diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property index 3a46611d..3a46611d 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Flags_Property diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection index 3d58fee0..3d58fee0 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_GSM_Connection diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection index 3a984b77..3a984b77 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_InfiniBand_Connection diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID index 2bacb725..2bacb725 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2 index 20240251..20240251 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlike_SSID_2 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID index 6d2bc0fa..6d2bc0fa 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Intlist_SSID diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format index b2bf9155..b2bf9155 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_IB_Old_Format diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format index 9427b16c..9427b16c 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_MAC_Old_Format diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID index 138380d0..138380d0 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_ID_UUID diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags index 330adda0..330adda0 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Flags diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting index 95d7b9a9..95d7b9a9 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Missing_Vlan_Setting diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name index f27cd4a3..f27cd4a3 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names index d9ac5864..d9ac5864 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID index 4a3b56d2..4a3b56d2 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_String_SSID diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config index 14280eef..14280eef 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_TC_Config diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection index f9ccc003..f9ccc003 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6 index a42dd5d2..a42dd5d2 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_IP6 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case index 29aef494..29aef494 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_Connection_MAC_Case diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob index 62e6ae31..62e6ae31 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Blob diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New index 4cd86686..4cd86686 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_New diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old index d3da598c..d3da598c 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Old diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing index 2b39538e..2b39538e 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wired_TLS_Path_Missing diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection index b1949d0d..b1949d0d 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_Wireless_Connection diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection index 16d4b45e..16d4b45e 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_dcb_connection diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 index cac135ad..cac135ad 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_1 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 index bbf2d8d6..bbf2d8d6 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_2 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 index d3122d53..d3122d53 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_1 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 index eb1cdace..eb1cdace 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_2 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 index 7419e97d..7419e97d 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_3 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 index 626b6f68..626b6f68 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/Test_minimal_slave_4 diff --git a/src/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem b/src/core/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem index ef1be20d..ef1be20d 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/test-ca-cert.pem diff --git a/src/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem b/src/core/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem index dec9aa1b..dec9aa1b 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem +++ b/src/core/settings/plugins/keyfile/tests/keyfiles/test-key-and-cert.pem diff --git a/src/core/settings/plugins/keyfile/tests/meson.build b/src/core/settings/plugins/keyfile/tests/meson.build new file mode 100644 index 00000000..3c89bcf9 --- /dev/null +++ b/src/core/settings/plugins/keyfile/tests/meson.build @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +exe = executable( + 'test-keyfile-settings', + 'test-keyfile-settings.c', + dependencies: libNetworkManagerTest_dep, + c_args: test_c_flags, +) + +test( + 'test-keyfile-settings', + test_script, + args: test_args + [exe.full_path()], + timeout: default_test_timeout, +) diff --git a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c index 4e8d89b1..348b0ed6 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c +++ b/src/core/settings/plugins/keyfile/tests/test-keyfile-settings.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2017 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> @@ -12,6 +12,8 @@ #include <arpa/inet.h> #include <sys/socket.h> #include <linux/pkt_sched.h> +#include <linux/if_ether.h> +#include <linux/if_infiniband.h> #include "nm-core-internal.h" @@ -21,8 +23,8 @@ #include "nm-test-utils-core.h" -#define TEST_KEYFILES_DIR NM_BUILD_SRCDIR "/src/settings/plugins/keyfile/tests/keyfiles" -#define TEST_SCRATCH_DIR NM_BUILD_BUILDDIR "/src/settings/plugins/keyfile/tests/keyfiles" +#define TEST_KEYFILES_DIR NM_BUILD_SRCDIR "/src/core/settings/plugins/keyfile/tests/keyfiles" +#define TEST_SCRATCH_DIR NM_BUILD_BUILDDIR "/src/core/settings/plugins/keyfile/tests/keyfiles" /*****************************************************************************/ diff --git a/src/settings/plugins/meson.build b/src/core/settings/plugins/meson.build index cde0844b..d4338a30 100644 --- a/src/settings/plugins/meson.build +++ b/src/core/settings/plugins/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later if enable_ifcfg_rh subdir('ifcfg-rh') diff --git a/src/supplicant/nm-supplicant-config.c b/src/core/supplicant/nm-supplicant-config.c index 9a23f185..eab494b0 100644 --- a/src/supplicant/nm-supplicant-config.c +++ b/src/core/supplicant/nm-supplicant-config.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-supplicant-config.h" @@ -100,7 +100,7 @@ nm_supplicant_config_add_option_with_type(NMSupplicantConfig *self, const char * value, gint32 len, NMSupplOptType opt_type, - const char * hidden, + const char * display_value, GError ** error) { NMSupplicantConfigPrivate *priv; @@ -138,7 +138,7 @@ nm_supplicant_config_add_option_with_type(NMSupplicantConfig *self, NM_SUPPLICANT_ERROR_CONFIG, "key '%s' and/or value %s invalid", key, - hidden ?: str); + display_value ?: str); return FALSE; } } @@ -165,7 +165,10 @@ nm_supplicant_config_add_option_with_type(NMSupplicantConfig *self, char buf[255]; memset(&buf[0], 0, sizeof(buf)); memcpy(&buf[0], opt->value, opt->len > 254 ? 254 : opt->len); - nm_log_info(LOGD_SUPPLICANT, "Config: added '%s' value '%s'", key, hidden ?: &buf[0]); + nm_log_info(LOGD_SUPPLICANT, + "Config: added '%s' value '%s'", + key, + display_value ?: &buf[0]); } g_hash_table_insert(priv->config, g_strdup(key), opt); @@ -178,7 +181,7 @@ nm_supplicant_config_add_option(NMSupplicantConfig *self, const char * key, const char * value, gint32 len, - const char * hidden, + const char * display_value, GError ** error) { return nm_supplicant_config_add_option_with_type(self, @@ -186,7 +189,7 @@ nm_supplicant_config_add_option(NMSupplicantConfig *self, value, len, NM_SUPPL_OPT_TYPE_INVALID, - hidden, + display_value, error); } @@ -455,7 +458,7 @@ nm_supplicant_config_add_setting_macsec(NMSupplicantConfig *self, "mka_ckn", (char *) buffer_ckn, sizeof(buffer_ckn), - NULL, + value, error)) return FALSE; } @@ -621,7 +624,8 @@ nm_supplicant_config_add_bgscan(NMSupplicantConfig *self, NMConnection *connecti || ((s_wsec = nm_connection_get_setting_wireless_security(connection)) && NM_IN_STRSET(nm_setting_wireless_security_get_key_mgmt(s_wsec), "ieee8021x", - "wpa-eap"))) + "wpa-eap", + "wpa-eap-suite-b-192"))) bgscan = "simple:30:-65:300"; return nm_supplicant_config_add_option(self, "bgscan", bgscan, -1, FALSE, error); @@ -632,7 +636,7 @@ add_string_val(NMSupplicantConfig *self, const char * field, const char * name, gboolean ucase, - const char * hidden, + const char * display_value, GError ** error) { if (field) { @@ -642,7 +646,12 @@ add_string_val(NMSupplicantConfig *self, value = g_ascii_strup(field, -1); field = value; } - return nm_supplicant_config_add_option(self, name, field, strlen(field), hidden, error); + return nm_supplicant_config_add_option(self, + name, + field, + strlen(field), + display_value, + error); } return TRUE; } @@ -655,7 +664,7 @@ add_string_val(NMSupplicantConfig *self, name, \ separator, \ ucase, \ - hidden, \ + display_value, \ error) \ ({ \ typeof(*(setting)) *_setting = (setting); \ @@ -684,7 +693,7 @@ add_string_val(NMSupplicantConfig *self, (name), \ _str->str, \ -1, \ - (hidden), \ + (display_value), \ (error))) \ _success = FALSE; \ } \ @@ -833,8 +842,13 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-psk"); } else if (nm_streq(key_mgmt, "wpa-eap")) { - if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_PMF)) { g_string_append(key_mgmt_conf, " wpa-eap-sha256"); + + if (_get_capability(priv, NM_SUPPL_CAP_TYPE_SUITEB192) + && pmf == NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED) + g_string_append(key_mgmt_conf, " wpa-eap-suite-b-192"); + } if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-eap"); if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT) @@ -863,6 +877,11 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } else if (nm_streq(key_mgmt, "sae")) { if (_get_capability(priv, NM_SUPPL_CAP_TYPE_FT)) g_string_append(key_mgmt_conf, " ft-sae"); + } else if (nm_streq(key_mgmt, "wpa-eap-suite-b-192")) { + pmf = NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED; + if (!nm_supplicant_config_add_option(self, "pairwise", "GCMP-256", -1, NULL, error) + || !nm_supplicant_config_add_option(self, "group", "GCMP-256", -1, NULL, error)) + return FALSE; } if (!add_string_val(self, key_mgmt_conf->str, "key_mgmt", TRUE, NULL, error)) @@ -932,7 +951,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } /* Don't try to enable PMF on non-WPA/SAE/OWE networks */ - if (!NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-psk", "sae", "owe")) + if (!NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192", "wpa-psk", "sae", "owe")) pmf = NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE; /* Check if we actually support PMF */ @@ -1050,7 +1069,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * } } else { /* 802.1x for Dynamic WEP and WPA-Enterprise */ - if (NM_IN_STRSET(key_mgmt, "ieee8021x", "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "ieee8021x", "wpa-eap", "wpa-eap-suite-b-192")) { if (!setting_8021x) { g_set_error(error, NM_SUPPLICANT_ERROR, @@ -1068,7 +1087,7 @@ nm_supplicant_config_add_setting_wireless_security(NMSupplicantConfig * return FALSE; } - if (nm_streq(key_mgmt, "wpa-eap")) { + if (NM_IN_STRSET(key_mgmt, "wpa-eap", "wpa-eap-suite-b-192")) { /* When using WPA-Enterprise, we want to use Proactive Key Caching (also * called Opportunistic Key Caching) to avoid full EAP exchanges when * roaming between access points in the same mobility group. diff --git a/src/supplicant/nm-supplicant-config.h b/src/core/supplicant/nm-supplicant-config.h index 21f1e0dc..b5619362 100644 --- a/src/supplicant/nm-supplicant-config.h +++ b/src/core/supplicant/nm-supplicant-config.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. diff --git a/src/supplicant/nm-supplicant-interface.c b/src/core/supplicant/nm-supplicant-interface.c index 77254c7e..6d9c604f 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/core/supplicant/nm-supplicant-interface.c @@ -1,14 +1,15 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-supplicant-interface.h" #include <stdio.h> +#include <linux/if_ether.h> #include "NetworkManagerUtils.h" #include "nm-core-internal.h" @@ -280,6 +281,8 @@ security_from_vardict(GVariant *security) flags |= NM_802_11_AP_SEC_KEY_MGMT_SAE; if (g_strv_contains(array, "owe")) flags |= NM_802_11_AP_SEC_KEY_MGMT_OWE; + if (g_strv_contains(array, "wpa-eap-suite-b-192")) + flags |= NM_802_11_AP_SEC_KEY_MGMT_EAP_SUITE_B_192; g_free(array); } @@ -457,9 +460,7 @@ _notify_maybe_scanning(NMSupplicantInterface *self) NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self); gboolean scanning; - scanning = - nm_supplicant_interface_state_is_operational(priv->state) - && (priv->scanning_property || priv->supp_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING); + scanning = nm_supplicant_interface_state_is_operational(priv->state) && priv->scanning_property; if (priv->scanning_cached == scanning) return; @@ -584,7 +585,7 @@ _bss_info_properties_changed(NMSupplicantInterface *self, if (v_v) { if (g_variant_lookup(v_v, "Type", "&s", &v_s)) { - p_ap_flags = NM_802_11_AP_FLAGS_WPS; + f = NM_802_11_AP_FLAGS_WPS; if (nm_streq(v_s, "pcb")) f |= NM_802_11_AP_FLAGS_WPS_PBC; else if (nm_streq(v_s, "pin")) @@ -668,19 +669,17 @@ _bss_info_properties_changed(NMSupplicantInterface *self, if (arr_len != 0) { nm_assert(arr_len == sizeof(bss_info->bssid)); bss_info->bssid_valid = TRUE; - memcpy(bss_info->bssid, arr_data, sizeof(bss_info->bssid)); + memcpy(&bss_info->bssid, arr_data, sizeof(bss_info->bssid)); } else if (bss_info->bssid_valid) { bss_info->bssid_valid = FALSE; - memset(bss_info->bssid, 0, sizeof(bss_info->bssid)); + memset(&bss_info->bssid, 0, sizeof(bss_info->bssid)); } g_variant_unref(v_v); } else { nm_assert(!initial || !bss_info->bssid_valid); } - nm_assert( - (bss_info->bssid_valid && !nm_utils_memeqzero(bss_info->bssid, sizeof(bss_info->bssid))) - || (!bss_info->bssid_valid - && nm_utils_memeqzero(bss_info->bssid, sizeof(bss_info->bssid)))); + nm_assert((!!bss_info->bssid_valid) + == (!nm_utils_memeqzero(&bss_info->bssid, sizeof(bss_info->bssid)))); p_max_rate_has = FALSE; p_max_rate = 0; @@ -1322,6 +1321,54 @@ nm_supplicant_interface_get_capabilities(NMSupplicantInterface *self) return caps; } +static void +set_bridge_cb(GVariant *ret, GError *error, gpointer user_data) +{ + NMSupplicantInterface *self; + NMLogLevel level; + gs_free const char * bridge = NULL; + + nm_utils_user_data_unpack(user_data, &self, &bridge); + + if (nm_utils_error_is_cancelled(error)) + return; + + /* The supplicant supports writing the bridge property since + * version 2.10. Before that version, trying to set the property + * results in a InvalidArgs error. Don't log a warning unless we + * are trying to set a non-NULL bridge. */ + if (!error) + level = LOGL_DEBUG; + else if (bridge == NULL && g_error_matches(error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS)) { + level = LOGL_DEBUG; + } else + level = LOGL_WARN; + + _NMLOG(level, + "set bridge %s%s%s result: %s", + NM_PRINT_FMT_QUOTE_STRING(bridge), + error ? error->message : "success"); +} + +void +nm_supplicant_interface_set_bridge(NMSupplicantInterface *self, const char *bridge) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self); + + _LOGT("set bridge %s%s%s", NM_PRINT_FMT_QUOTE_STRING(bridge)); + + nm_dbus_connection_call_set(priv->dbus_connection, + priv->name_owner->str, + priv->object_path->str, + NM_WPAS_DBUS_IFACE_INTERFACE, + "BridgeIfname", + g_variant_new_string(bridge ?: ""), + DBUS_TIMEOUT_MSEC, + priv->main_cancellable, + set_bridge_cb, + nm_utils_user_data_pack(self, g_strdup(bridge))); +} + void nm_supplicant_interface_set_global_capabilities(NMSupplicantInterface *self, NMSupplCapMask value) { diff --git a/src/supplicant/nm-supplicant-interface.h b/src/core/supplicant/nm-supplicant-interface.h index 812ea193..a62eeb62 100644 --- a/src/supplicant/nm-supplicant-interface.h +++ b/src/core/supplicant/nm-supplicant-interface.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2017 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. @@ -190,4 +190,6 @@ void nm_supplicant_interface_cancel_wps(NMSupplicantInterface *self); NMSupplicantAuthState nm_supplicant_interface_get_auth_state(NMSupplicantInterface *self); +void nm_supplicant_interface_set_bridge(NMSupplicantInterface *self, const char *bridge); + #endif /* __NM_SUPPLICANT_INTERFACE_H__ */ diff --git a/src/supplicant/nm-supplicant-manager.c b/src/core/supplicant/nm-supplicant-manager.c index a166f619..32554187 100644 --- a/src/supplicant/nm-supplicant-manager.c +++ b/src/core/supplicant/nm-supplicant-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2010 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-supplicant-manager.h" @@ -933,6 +933,7 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_AP, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_PMF, NM_TERNARY_FALSE); _caps_set(priv, NM_SUPPL_CAP_TYPE_FILS, NM_TERNARY_FALSE); + _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_FALSE); if (array) { for (a = array; *a; a++) { if (nm_streq(*a, "ap")) { @@ -963,6 +964,10 @@ _dbus_get_capabilities_cb(GVariant *res, GError *error, gpointer user_data) _caps_set(priv, NM_SUPPL_CAP_TYPE_MESH, NM_TERNARY_TRUE); continue; } + if (nm_streq(*a, "suiteb192")) { + _caps_set(priv, NM_SUPPL_CAP_TYPE_SUITEB192, NM_TERNARY_TRUE); + continue; + } } } } diff --git a/src/supplicant/nm-supplicant-manager.h b/src/core/supplicant/nm-supplicant-manager.h index aaeb41e6..3000d064 100644 --- a/src/supplicant/nm-supplicant-manager.h +++ b/src/core/supplicant/nm-supplicant-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2008 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/core/supplicant/nm-supplicant-settings-verify.c index c7209f5f..3f0a33e0 100644 --- a/src/supplicant/nm-supplicant-settings-verify.c +++ b/src/core/supplicant/nm-supplicant-settings-verify.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2012 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-supplicant-settings-verify.h" @@ -63,7 +63,7 @@ static const struct Opt opt_table[] = { OPT_INT("fragment_size", 1, 2000), OPT_KEYWORD("freq_list", NULL), OPT_INT("frequency", 2412, 5825), - OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", )), + OPT_KEYWORD("group", NM_MAKE_STRV("CCMP", "TKIP", "WEP104", "WEP40", "GCMP-256", )), OPT_BYTES("identity", 0), OPT_INT("ieee80211w", 0, 2), OPT_INT("ignore_broadcast_ssid", 0, 2), @@ -82,6 +82,7 @@ static const struct Opt opt_table[] = { "FT-FILS-SHA384", "IEEE8021X", "SAE", + "WPA-EAP-SUITE-B-192", "FT-SAE", "OWE", "NONE", )), @@ -92,7 +93,7 @@ static const struct Opt opt_table[] = { OPT_BYTES("mka_ckn", 65536), OPT_BYTES("nai", 0), OPT_BYTES("pac_file", 0), - OPT_KEYWORD("pairwise", NM_MAKE_STRV("CCMP", "TKIP", "NONE", )), + OPT_KEYWORD("pairwise", NM_MAKE_STRV("CCMP", "TKIP", "GCMP-256", "NONE", )), OPT_UTF8("password", 0), OPT_BYTES("pcsc", 0), OPT_KEYWORD("phase1", diff --git a/src/supplicant/nm-supplicant-settings-verify.h b/src/core/supplicant/nm-supplicant-settings-verify.h index 8a0c62c2..8ba50b67 100644 --- a/src/supplicant/nm-supplicant-settings-verify.h +++ b/src/core/supplicant/nm-supplicant-settings-verify.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2008 Red Hat, Inc. */ diff --git a/src/supplicant/nm-supplicant-types.h b/src/core/supplicant/nm-supplicant-types.h index e35059af..adcf02db 100644 --- a/src/supplicant/nm-supplicant-types.h +++ b/src/core/supplicant/nm-supplicant-types.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2006 - 2008 Red Hat, Inc. */ @@ -45,6 +45,7 @@ typedef enum { NM_SUPPL_CAP_TYPE_MESH, NM_SUPPL_CAP_TYPE_FAST, NM_SUPPL_CAP_TYPE_WFD, + NM_SUPPL_CAP_TYPE_SUITEB192, _NM_SUPPL_CAP_TYPE_NUM, } NMSupplCapType; @@ -158,7 +159,7 @@ typedef struct _NMSupplicantBssInfo { guint8 signal_percent; - guint8 bssid[6 /* ETH_ALEN */]; + NMEtherAddr bssid; NM80211ApFlags ap_flags : 5; diff --git a/src/supplicant/tests/certs/test-ca-cert.pem b/src/core/supplicant/tests/certs/test-ca-cert.pem index ef1be20d..ef1be20d 100644 --- a/src/supplicant/tests/certs/test-ca-cert.pem +++ b/src/core/supplicant/tests/certs/test-ca-cert.pem diff --git a/src/supplicant/tests/certs/test-cert.p12 b/src/core/supplicant/tests/certs/test-cert.p12 index ae4a6830..ae4a6830 100644 --- a/src/supplicant/tests/certs/test-cert.p12 +++ b/src/core/supplicant/tests/certs/test-cert.p12 Binary files differdiff --git a/src/supplicant/tests/meson.build b/src/core/supplicant/tests/meson.build index 63012d10..88832a9b 100644 --- a/src/supplicant/tests/meson.build +++ b/src/core/supplicant/tests/meson.build @@ -1,11 +1,11 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_unit = 'test-supplicant-config' exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/core/supplicant/tests/test-supplicant-config.c index 6edcd8da..99729c18 100644 --- a/src/supplicant/tests/test-supplicant-config.c +++ b/src/core/supplicant/tests/test-supplicant-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2008 - 2011 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <stdio.h> #include <stdarg.h> @@ -21,7 +21,7 @@ #include "nm-test-utils-core.h" -#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/supplicant/tests/certs" +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/core/supplicant/tests/certs" /*****************************************************************************/ @@ -600,6 +600,50 @@ generate_wifi_eap_connection(const char * id, return connection; } +static NMConnection * +generate_wifi_eap_suite_b_192_connection(const char *id, GBytes *ssid, const char *bssid_str) +{ + NMConnection * connection = NULL; + NMSettingWirelessSecurity *s_wsec; + NMSetting8021x * s_8021x; + gboolean success; + GError * error = NULL; + + connection = new_basic_connection(id, ssid, bssid_str); + + /* Wifi Security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new(); + nm_connection_add_setting(connection, NM_SETTING(s_wsec)); + g_object_set(s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap-suite-b-192", NULL); + + /* 802-1X setting */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_connection_add_setting(connection, NM_SETTING(s_8021x)); + nm_setting_802_1x_add_eap_method(s_8021x, "tls"); + nm_setting_802_1x_set_client_cert(s_8021x, + TEST_CERT_DIR "/test-cert.p12", + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL); + g_assert(nm_setting_802_1x_set_ca_cert(s_8021x, + TEST_CERT_DIR "/test-ca-cert.pem", + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL)); + nm_setting_802_1x_set_private_key(s_8021x, + TEST_CERT_DIR "/test-cert.p12", + NULL, + NM_SETTING_802_1X_CK_SCHEME_PATH, + NULL, + NULL); + + success = nm_connection_verify(connection, &error); + g_assert_no_error(error); + g_assert(success); + + return connection; +} + static void test_wifi_eap_locked_bssid(void) { @@ -755,6 +799,47 @@ test_wifi_eap_fils_disabled(void) validate_opt("wifi-eap", config_dict, "bgscan", NM_SUPPL_OPT_TYPE_BYTES, bgscan); } +static void +test_wifi_eap_suite_b_generation(void) +{ + gs_unref_object NMConnection *connection = NULL; + gs_unref_variant GVariant *config_dict = NULL; + const unsigned char ssid_data[] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44}; + gs_unref_bytes GBytes *ssid = g_bytes_new(ssid_data, sizeof(ssid_data)); + const char * bssid_str = "11:22:33:44:55:66"; + guint32 mtu = 1100; + + connection = generate_wifi_eap_suite_b_192_connection("EAP-TLS Suite B 192", ssid, bssid_str); + + NMTST_EXPECT_NM_INFO("Config: added 'ssid' value 'Test SSID'*"); + NMTST_EXPECT_NM_INFO("Config: added 'scan_ssid' value '1'*"); + NMTST_EXPECT_NM_INFO("Config: added 'bssid' value '11:22:33:44:55:66'*"); + NMTST_EXPECT_NM_INFO("Config: added 'freq_list' value *"); + NMTST_EXPECT_NM_INFO("Config: added 'pairwise' value 'GCMP-256'"); + NMTST_EXPECT_NM_INFO("Config: added 'group' value 'GCMP-256'"); + NMTST_EXPECT_NM_INFO("Config: added 'key_mgmt' value 'WPA-EAP-SUITE-B-192'"); + NMTST_EXPECT_NM_INFO("Config: added 'eap' value 'TLS'"); + NMTST_EXPECT_NM_INFO("Config: added 'fragment_size' value '1086'"); + NMTST_EXPECT_NM_INFO("Config: added 'ca_cert' value '*/test-ca-cert.pem'"); + NMTST_EXPECT_NM_INFO("Config: added 'private_key' value '*/test-cert.p12'"); + NMTST_EXPECT_NM_INFO("Config: added 'proactive_key_caching' value '1'"); + config_dict = build_supplicant_config(connection, mtu, 0, NM_SUPPL_CAP_MASK_T_PMF_YES); + g_test_assert_expected_messages(); + g_assert(config_dict); + + validate_opt("wifi-eap", config_dict, "scan_ssid", NM_SUPPL_OPT_TYPE_INT, GINT_TO_POINTER(1)); + validate_opt("wifi-eap", config_dict, "ssid", NM_SUPPL_OPT_TYPE_BYTES, ssid); + validate_opt("wifi-eap", config_dict, "bssid", NM_SUPPL_OPT_TYPE_KEYWORD, bssid_str); + validate_opt("wifi-eap", + config_dict, + "key_mgmt", + NM_SUPPL_OPT_TYPE_KEYWORD, + "WPA-EAP-SUITE-B-192"); + validate_opt("wifi-eap", config_dict, "eap", NM_SUPPL_OPT_TYPE_KEYWORD, "TLS"); + validate_opt("wifi-eap", config_dict, "pairwise", NM_SUPPL_OPT_TYPE_KEYWORD, "GCMP-256"); + validate_opt("wifi-eap", config_dict, "group", NM_SUPPL_OPT_TYPE_KEYWORD, "GCMP-256"); +} + /*****************************************************************************/ static void @@ -818,6 +903,7 @@ main(int argc, char **argv) g_test_add_func("/supplicant-config/wifi-eap/fils-disabled", test_wifi_eap_fils_disabled); g_test_add_func("/supplicant-config/wifi-sae", test_wifi_sae); g_test_add_func("/supplicant-config/test_suppl_cap_mask", test_suppl_cap_mask); + g_test_add_func("/supplicant-config/wifi-eap-suite-b-192", test_wifi_eap_suite_b_generation); return g_test_run(); } diff --git a/src/core/systemd/meson.build b/src/core/systemd/meson.build new file mode 100644 index 00000000..70f6b542 --- /dev/null +++ b/src/core/systemd/meson.build @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +incs = include_directories( + 'sd-adapt-core', + 'src/libsystemd-network', + 'src/libsystemd/sd-event', + 'src/systemd', +) + +libnm_systemd_core = static_library( + 'nm-systemd-core', + sources: files( + 'src/libsystemd-network/arp-util.c', + 'src/libsystemd-network/dhcp-identifier.c', + 'src/libsystemd-network/dhcp-network.c', + 'src/libsystemd-network/dhcp-option.c', + 'src/libsystemd-network/dhcp-packet.c', + 'src/libsystemd-network/dhcp6-network.c', + 'src/libsystemd-network/dhcp6-option.c', + 'src/libsystemd-network/lldp-neighbor.c', + 'src/libsystemd-network/lldp-network.c', + 'src/libsystemd-network/network-internal.c', + 'src/libsystemd-network/sd-dhcp-client.c', + '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', + 'src/libsystemd/sd-id128/id128-util.c', + 'src/libsystemd/sd-id128/sd-id128.c', + 'nm-sd.c', + 'nm-sd-utils-core.c', + 'nm-sd-utils-dhcp.c', + 'sd-adapt-core/nm-sd-adapt-core.c', + ), + include_directories: [ + incs, + src_inc, + ], + dependencies: [ + glib_nm_default_dep, + libnm_core_dep, + libnm_systemd_shared_dep, + ], + c_args: [ + '-DG_LOG_DOMAIN="NetworkManager"', + ], + link_with: libc_siphash, +) + +libnm_systemd_core_dep = declare_dependency( + include_directories: incs, + dependencies: [ + glib_dep, + libnm_core_dep, + libnm_systemd_shared_dep, + ], + link_with: libnm_systemd_core, +) diff --git a/src/core/systemd/nm-default-systemd.h b/src/core/systemd/nm-default-systemd.h new file mode 100644 index 00000000..1979d9c9 --- /dev/null +++ b/src/core/systemd/nm-default-systemd.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_DEFAULT_SYSTEMD_H__ +#define __NM_DEFAULT_SYSTEMD_H__ + +/*****************************************************************************/ + +#include "nm-default-daemon.h" + +#undef NETWORKMANAGER_COMPILATION +#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_SYSTEMD + +/*****************************************************************************/ + +#endif /* __NM_DEFAULT_SYSTEMD_H__ */ diff --git a/src/systemd/nm-sd-utils-core.c b/src/core/systemd/nm-sd-utils-core.c index 804c7282..af68603e 100644 --- a/src/systemd/nm-sd-utils-core.c +++ b/src/core/systemd/nm-sd-utils-core.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include "nm-sd-utils-core.h" diff --git a/src/systemd/nm-sd-utils-core.h b/src/core/systemd/nm-sd-utils-core.h index 440e6349..ccad0029 100644 --- a/src/systemd/nm-sd-utils-core.h +++ b/src/core/systemd/nm-sd-utils-core.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2018 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd-utils-dhcp.c b/src/core/systemd/nm-sd-utils-dhcp.c index 01be2308..b5aa315a 100644 --- a/src/systemd/nm-sd-utils-dhcp.c +++ b/src/core/systemd/nm-sd-utils-dhcp.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include "nm-sd-utils-dhcp.h" diff --git a/src/systemd/nm-sd-utils-dhcp.h b/src/core/systemd/nm-sd-utils-dhcp.h index e456012b..5d126d5b 100644 --- a/src/systemd/nm-sd-utils-dhcp.h +++ b/src/core/systemd/nm-sd-utils-dhcp.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019 Red Hat, Inc. */ diff --git a/src/systemd/nm-sd.c b/src/core/systemd/nm-sd.c index 89c12337..11f3abbd 100644 --- a/src/systemd/nm-sd.c +++ b/src/core/systemd/nm-sd.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include "nm-sd.h" diff --git a/src/systemd/nm-sd.h b/src/core/systemd/nm-sd.h index 7cea9b68..0ea4be22 100644 --- a/src/systemd/nm-sd.h +++ b/src/core/systemd/nm-sd.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ diff --git a/src/systemd/sd-adapt-core/condition.h b/src/core/systemd/sd-adapt-core/condition.h index d3a6812a..d3a6812a 100644 --- a/src/systemd/sd-adapt-core/condition.h +++ b/src/core/systemd/sd-adapt-core/condition.h diff --git a/src/systemd/sd-adapt-core/conf-parser.h b/src/core/systemd/sd-adapt-core/conf-parser.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/conf-parser.h +++ b/src/core/systemd/sd-adapt-core/conf-parser.h diff --git a/src/systemd/sd-adapt-core/device-util.h b/src/core/systemd/sd-adapt-core/device-util.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/device-util.h +++ b/src/core/systemd/sd-adapt-core/device-util.h diff --git a/src/systemd/sd-adapt-core/khash.h b/src/core/systemd/sd-adapt-core/khash.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/khash.h +++ b/src/core/systemd/sd-adapt-core/khash.h diff --git a/src/systemd/sd-adapt-core/sd-daemon.h b/src/core/systemd/sd-adapt-core/network-util.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/sd-daemon.h +++ b/src/core/systemd/sd-adapt-core/network-util.h diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c index f0f85c43..9339b33d 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.c +++ b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include "nm-sd-adapt-core.h" diff --git a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h index 0ec6ade1..f627d7d4 100644 --- a/src/systemd/sd-adapt-core/nm-sd-adapt-core.h +++ b/src/core/systemd/sd-adapt-core/nm-sd-adapt-core.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2014 - 2018 Red Hat, Inc. */ @@ -6,13 +6,16 @@ #ifndef __NM_SD_ADAPT_CORE_H__ #define __NM_SD_ADAPT_CORE_H__ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include <stdbool.h> #include <sys/resource.h> #include <time.h> +#undef NETWORKMANAGER_COMPILATION #include "systemd/sd-adapt-shared/nm-sd-adapt-shared.h" +#undef NETWORKMANAGER_COMPILATION +#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_SYSTEMD #ifndef HAVE_SYS_AUXV_H #define HAVE_SYS_AUXV_H 0 diff --git a/src/systemd/sd-adapt-core/sd-device.h b/src/core/systemd/sd-adapt-core/sd-daemon.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/sd-device.h +++ b/src/core/systemd/sd-adapt-core/sd-daemon.h diff --git a/src/systemd/sd-adapt-core/udev-util.h b/src/core/systemd/sd-adapt-core/sd-device.h index 637892c2..637892c2 100644 --- a/src/systemd/sd-adapt-core/udev-util.h +++ b/src/core/systemd/sd-adapt-core/sd-device.h diff --git a/src/core/systemd/sd-adapt-core/udev-util.h b/src/core/systemd/sd-adapt-core/udev-util.h new file mode 100644 index 00000000..637892c2 --- /dev/null +++ b/src/core/systemd/sd-adapt-core/udev-util.h @@ -0,0 +1,3 @@ +#pragma once + +/* dummy header */ diff --git a/src/systemd/src/libsystemd-network/arp-util.c b/src/core/systemd/src/libsystemd-network/arp-util.c index b2ac2c9c..1c777d8a 100644 --- a/src/systemd/src/libsystemd-network/arp-util.c +++ b/src/core/systemd/src/libsystemd-network/arp-util.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/arp-util.h b/src/core/systemd/src/libsystemd-network/arp-util.h index 9a4427e8..2dac8cfb 100644 --- a/src/systemd/src/libsystemd-network/arp-util.h +++ b/src/core/systemd/src/libsystemd-network/arp-util.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.c b/src/core/systemd/src/libsystemd-network/dhcp-identifier.c index 026015a7..0720e381 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.c +++ b/src/core/systemd/src/libsystemd-network/dhcp-identifier.c @@ -1,8 +1,9 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" #include <linux/if_infiniband.h> +#include <net/ethernet.h> #include <net/if_arp.h> #include "sd-device.h" @@ -10,7 +11,7 @@ #include "dhcp-identifier.h" #include "dhcp6-protocol.h" -#include "network-internal.h" +#include "network-util.h" #include "siphash24.h" #include "sparse-endian.h" #include "stdio-util.h" @@ -28,11 +29,10 @@ int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) { if (duid_len > MAX_DUID_LEN) return -EINVAL; - if (!strict) { + if (!strict) /* Strict validation is not requested. We only ensure that the * DUID is not too long. */ return 0; - } switch (duid_type) { case DUID_TYPE_LLT: diff --git a/src/systemd/src/libsystemd-network/dhcp-identifier.h b/src/core/systemd/src/libsystemd-network/dhcp-identifier.h index 76abd658..e9f2ea7e 100644 --- a/src/systemd/src/libsystemd-network/dhcp-identifier.h +++ b/src/core/systemd/src/libsystemd-network/dhcp-identifier.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include "sd-id128.h" diff --git a/src/systemd/src/libsystemd-network/dhcp-internal.h b/src/core/systemd/src/libsystemd-network/dhcp-internal.h index 7e814948..40e6b1f2 100644 --- a/src/systemd/src/libsystemd-network/dhcp-internal.h +++ b/src/core/systemd/src/libsystemd-network/dhcp-internal.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** @@ -29,10 +29,10 @@ typedef struct DHCPServerData { extern const struct hash_ops dhcp_option_hash_ops; -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, - uint32_t xid, const uint8_t *mac_addr, - size_t mac_addr_len, uint16_t arp_type, - uint16_t port); +int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, + const uint8_t *mac_addr, size_t mac_addr_len, + const uint8_t *bcast_addr, size_t bcast_addr_len, + uint16_t arp_type, uint16_t port); int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type); int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len); diff --git a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h b/src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h index 66222ead..49392d1b 100644 --- a/src/systemd/src/libsystemd-network/dhcp-lease-internal.h +++ b/src/core/systemd/src/libsystemd-network/dhcp-lease-internal.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/core/systemd/src/libsystemd-network/dhcp-network.c index 1f01ece1..4477f46f 100644 --- a/src/systemd/src/libsystemd-network/dhcp-network.c +++ b/src/core/systemd/src/libsystemd-network/dhcp-network.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2013 Intel Corporation. All rights reserved. ***/ @@ -21,9 +21,9 @@ #include "unaligned.h" static int _bind_raw_socket(int ifindex, union sockaddr_union *link, - uint32_t xid, const uint8_t *mac_addr, - size_t mac_addr_len, + uint32_t xid, const uint8_t *bcast_addr, + size_t bcast_addr_len, const struct ether_addr *eth_mac, uint16_t arp_type, uint8_t dhcp_hlen, uint16_t port) { @@ -106,9 +106,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, .sll_protocol = htobe16(ETH_P_IP), .sll_ifindex = ifindex, .sll_hatype = htobe16(arp_type), - .sll_halen = mac_addr_len, + .sll_halen = bcast_addr_len, }; - memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len); + memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len); /* We may overflow link->ll. link->ll_buffer ensures we have enough space. */ r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll)); if (r < 0) @@ -117,34 +117,44 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link, return TAKE_FD(s); } -int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, - uint32_t xid, const uint8_t *mac_addr, - size_t mac_addr_len, uint16_t arp_type, - uint16_t port) { +int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid, + const uint8_t *mac_addr, size_t mac_addr_len, + const uint8_t *bcast_addr, size_t bcast_addr_len, + uint16_t arp_type, uint16_t port) { static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* Default broadcast address for IPoIB */ static const uint8_t ib_bcast[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff - }; + }; struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } }; - const uint8_t *bcast_addr = NULL; + const uint8_t *default_bcast_addr; + size_t expected_bcast_addr_len; uint8_t dhcp_hlen = 0; if (arp_type == ARPHRD_ETHER) { assert_return(mac_addr_len == ETH_ALEN, -EINVAL); memcpy(ð_mac, mac_addr, ETH_ALEN); - bcast_addr = eth_bcast; dhcp_hlen = ETH_ALEN; + + default_bcast_addr = eth_bcast; + expected_bcast_addr_len = ETH_ALEN; } else if (arp_type == ARPHRD_INFINIBAND) { - assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL); - bcast_addr = ib_bcast; + default_bcast_addr = ib_bcast; + expected_bcast_addr_len = INFINIBAND_ALEN; } else return -EINVAL; - return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len, - bcast_addr, ð_mac, arp_type, dhcp_hlen, port); + if (bcast_addr && bcast_addr_len > 0) + assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL); + else { + bcast_addr = default_bcast_addr; + bcast_addr_len = expected_bcast_addr_len; + } + + return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len, + ð_mac, arp_type, dhcp_hlen, port); } int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) { diff --git a/src/systemd/src/libsystemd-network/dhcp-option.c b/src/core/systemd/src/libsystemd-network/dhcp-option.c index 3a0f5155..2c15d85a 100644 --- a/src/systemd/src/libsystemd-network/dhcp-option.c +++ b/src/core/systemd/src/libsystemd-network/dhcp-option.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2013 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/dhcp-packet.c b/src/core/systemd/src/libsystemd-network/dhcp-packet.c index 2062be91..eeadd562 100644 --- a/src/systemd/src/libsystemd-network/dhcp-packet.c +++ b/src/core/systemd/src/libsystemd-network/dhcp-packet.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2013 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/dhcp-protocol.h b/src/core/systemd/src/libsystemd-network/dhcp-protocol.h index f0366324..11f4201a 100644 --- a/src/systemd/src/libsystemd-network/dhcp-protocol.h +++ b/src/core/systemd/src/libsystemd-network/dhcp-protocol.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp6-internal.h b/src/core/systemd/src/libsystemd-network/dhcp6-internal.h index 9ce6dcd0..24d8a314 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-internal.h +++ b/src/core/systemd/src/libsystemd-network/dhcp6-internal.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h b/src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h index df6c95e0..e9e2362d 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-lease-internal.h +++ b/src/core/systemd/src/libsystemd-network/dhcp6-lease-internal.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/dhcp6-network.c b/src/core/systemd/src/libsystemd-network/dhcp6-network.c index 449ff6c4..b6816de4 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-network.c +++ b/src/core/systemd/src/libsystemd-network/dhcp6-network.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/core/systemd/src/libsystemd-network/dhcp6-option.c index 25da477d..21e2d3f0 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/core/systemd/src/libsystemd-network/dhcp6-option.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014-2015 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/dhcp6-protocol.h b/src/core/systemd/src/libsystemd-network/dhcp6-protocol.h index f7a27028..c7003638 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-protocol.h +++ b/src/core/systemd/src/libsystemd-network/dhcp6-protocol.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once /*** diff --git a/src/systemd/src/libsystemd-network/lldp-internal.h b/src/core/systemd/src/libsystemd-network/lldp-internal.h index 9598438d..f23695f9 100644 --- a/src/systemd/src/libsystemd-network/lldp-internal.h +++ b/src/core/systemd/src/libsystemd-network/lldp-internal.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include "sd-event.h" diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.c b/src/core/systemd/src/libsystemd-network/lldp-neighbor.c index 9baa8e8c..58ff0e0f 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.c +++ b/src/core/systemd/src/libsystemd-network/lldp-neighbor.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" diff --git a/src/systemd/src/libsystemd-network/lldp-neighbor.h b/src/core/systemd/src/libsystemd-network/lldp-neighbor.h index 74175edf..a5718c8c 100644 --- a/src/systemd/src/libsystemd-network/lldp-neighbor.h +++ b/src/core/systemd/src/libsystemd-network/lldp-neighbor.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include <inttypes.h> diff --git a/src/systemd/src/libsystemd-network/lldp-network.c b/src/core/systemd/src/libsystemd-network/lldp-network.c index 85d53e71..75dce58c 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.c +++ b/src/core/systemd/src/libsystemd-network/lldp-network.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" diff --git a/src/systemd/src/libsystemd-network/lldp-network.h b/src/core/systemd/src/libsystemd-network/lldp-network.h index e4ed2898..bc69b324 100644 --- a/src/systemd/src/libsystemd-network/lldp-network.h +++ b/src/core/systemd/src/libsystemd-network/lldp-network.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include "sd-event.h" diff --git a/src/core/systemd/src/libsystemd-network/network-internal.c b/src/core/systemd/src/libsystemd-network/network-internal.c new file mode 100644 index 00000000..efa3dcfa --- /dev/null +++ b/src/core/systemd/src/libsystemd-network/network-internal.c @@ -0,0 +1,245 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "nm-sd-adapt-core.h" + +#include <arpa/inet.h> +#include <linux/if.h> +#include <netinet/ether.h> + +#include "sd-ndisc.h" + +#include "alloc-util.h" +#include "dhcp-lease-internal.h" +#include "extract-word.h" +#include "hexdecoct.h" +#include "log.h" +#include "network-internal.h" +#include "parse-util.h" + +size_t serialize_in_addrs(FILE *f, + const struct in_addr *addresses, + size_t size, + bool *with_leading_space, + bool (*predicate)(const struct in_addr *addr)) { + assert(f); + assert(addresses); + + size_t count = 0; + bool _space = false; + if (!with_leading_space) + with_leading_space = &_space; + + for (size_t i = 0; i < size; i++) { + char sbuf[INET_ADDRSTRLEN]; + + if (predicate && !predicate(&addresses[i])) + continue; + + if (*with_leading_space) + fputc(' ', f); + fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f); + count++; + *with_leading_space = true; + } + + return count; +} + +int deserialize_in_addrs(struct in_addr **ret, const char *string) { + _cleanup_free_ struct in_addr *addresses = NULL; + int size = 0; + + assert(ret); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + struct in_addr *new_addresses; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr)); + if (!new_addresses) + return -ENOMEM; + else + addresses = new_addresses; + + r = inet_pton(AF_INET, word, &(addresses[size])); + if (r <= 0) + continue; + + size++; + } + + *ret = size > 0 ? TAKE_PTR(addresses) : NULL; + + return size; +} + +void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size, bool *with_leading_space) { + assert(f); + assert(addresses); + assert(size); + + bool _space = false; + if (!with_leading_space) + with_leading_space = &_space; + + for (size_t i = 0; i < size; i++) { + char buffer[INET6_ADDRSTRLEN]; + + if (*with_leading_space) + fputc(' ', f); + fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); + *with_leading_space = true; + } +} + +int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { + _cleanup_free_ struct in6_addr *addresses = NULL; + int size = 0; + + assert(ret); + assert(string); + + for (;;) { + _cleanup_free_ char *word = NULL; + struct in6_addr *new_addresses; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr)); + if (!new_addresses) + return -ENOMEM; + else + addresses = new_addresses; + + r = inet_pton(AF_INET6, word, &(addresses[size])); + if (r <= 0) + continue; + + size++; + } + + *ret = TAKE_PTR(addresses); + + return size; +} + +void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { + assert(f); + assert(key); + assert(routes); + assert(size); + + fprintf(f, "%s=", key); + + for (size_t i = 0; i < size; i++) { + char sbuf[INET_ADDRSTRLEN]; + struct in_addr dest, gw; + uint8_t length; + + assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0); + assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); + assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); + + fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof sbuf), length); + fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof sbuf), i < size - 1 ? " ": ""); + } + + fputs("\n", f); +} + +int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { + _cleanup_free_ struct sd_dhcp_route *routes = NULL; + size_t size = 0, allocated = 0; + + assert(ret); + assert(ret_size); + assert(ret_allocated); + assert(string); + + /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ + for (;;) { + _cleanup_free_ char *word = NULL; + char *tok, *tok_end; + unsigned n; + int r; + + r = extract_first_word(&string, &word, NULL, 0); + if (r < 0) + return r; + if (r == 0) + break; + + if (!GREEDY_REALLOC(routes, allocated, size + 1)) + return -ENOMEM; + + tok = word; + + /* get the subnet */ + tok_end = strchr(tok, '/'); + if (!tok_end) + continue; + *tok_end = '\0'; + + r = inet_aton(tok, &routes[size].dst_addr); + if (r == 0) + continue; + + tok = tok_end + 1; + + /* get the prefixlen */ + tok_end = strchr(tok, ','); + if (!tok_end) + continue; + + *tok_end = '\0'; + + r = safe_atou(tok, &n); + if (r < 0 || n > 32) + continue; + + routes[size].dst_prefixlen = (uint8_t) n; + tok = tok_end + 1; + + /* get the gateway */ + r = inet_aton(tok, &routes[size].gw_addr); + if (r == 0) + continue; + + size++; + } + + *ret_size = size; + *ret_allocated = allocated; + *ret = TAKE_PTR(routes); + + return 0; +} + +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { + _cleanup_free_ char *hex_buf = NULL; + + assert(f); + assert(key); + assert(data); + + hex_buf = hexmem(data, size); + if (!hex_buf) + return -ENOMEM; + + fprintf(f, "%s=%s\n", key, hex_buf); + + return 0; +} diff --git a/src/core/systemd/src/libsystemd-network/network-internal.h b/src/core/systemd/src/libsystemd-network/network-internal.h new file mode 100644 index 00000000..e5b853c0 --- /dev/null +++ b/src/core/systemd/src/libsystemd-network/network-internal.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include <stdbool.h> +#include <stdio.h> + +#include "sd-dhcp-lease.h" + +size_t serialize_in_addrs(FILE *f, + const struct in_addr *addresses, + size_t size, + bool *with_leading_space, + bool (*predicate)(const struct in_addr *addr)); +int deserialize_in_addrs(struct in_addr **addresses, const char *string); +void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, + size_t size, + bool *with_leading_space); +int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); + +/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ +struct sd_dhcp_route; +struct sd_dhcp_lease; + +void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); +int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); + +/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ +int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); + +int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); +int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/core/systemd/src/libsystemd-network/sd-dhcp-client.c index 6849ed9e..27a3476f 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/core/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2013 Intel Corporation. All rights reserved. ***/ @@ -16,19 +16,22 @@ #include "sd-dhcp-client.h" #include "alloc-util.h" -#include "async.h" #include "dhcp-identifier.h" #include "dhcp-internal.h" #include "dhcp-lease-internal.h" #include "dhcp-protocol.h" #include "dns-domain.h" #include "event-util.h" +#include "fd-util.h" #include "hostname-util.h" #include "io-util.h" #include "memory-util.h" #include "random-util.h" +#include "set.h" +#include "sort-util.h" #include "string-util.h" #include "strv.h" +#include "time-util.h" #include "utf8.h" #include "web-util.h" @@ -38,6 +41,9 @@ #define RESTART_AFTER_NAK_MIN_USEC (1 * USEC_PER_SEC) #define RESTART_AFTER_NAK_MAX_USEC (30 * USEC_PER_MINUTE) +#define TRANSIENT_FAILURE_ATTEMPTS 3 /* Arbitrary limit: how many attempts are considered enough to report + * transient failure. */ + typedef struct sd_dhcp_client_id { uint8_t type; union { @@ -77,13 +83,13 @@ struct sd_dhcp_client { union sockaddr_union link; sd_event_source *receive_message; bool request_broadcast; - uint8_t *req_opts; - size_t req_opts_allocated; - size_t req_opts_size; + Set *req_opts; bool anonymize; be32_t last_addr; uint8_t mac_addr[MAX_MAC_ADDR_LEN]; size_t mac_addr_len; + uint8_t bcast_addr[MAX_MAC_ADDR_LEN]; + size_t bcast_addr_len; uint16_t arp_type; sd_dhcp_client_id client_id; size_t client_id_len; @@ -95,6 +101,9 @@ struct sd_dhcp_client { uint32_t fallback_lease_lifetime; uint32_t xid; usec_t start_time; + usec_t t1_time; + usec_t t2_time; + usec_t expire_time; uint64_t attempt; uint64_t max_attempts; OrderedHashmap *extra_options; @@ -232,8 +241,6 @@ int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast) } int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { - size_t i; - assert_return(client, -EINVAL); assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY); @@ -250,17 +257,7 @@ int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { break; } - for (i = 0; i < client->req_opts_size; i++) - if (client->req_opts[i] == option) - return -EEXIST; - - if (!GREEDY_REALLOC(client->req_opts, client->req_opts_allocated, - client->req_opts_size + 1)) - return -ENOMEM; - - client->req_opts[client->req_opts_size++] = option; - - return 0; + return set_ensure_put(&client->req_opts, NULL, UINT8_TO_PTR(option)); } int sd_dhcp_client_set_request_address( @@ -291,6 +288,7 @@ int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) { int sd_dhcp_client_set_mac( sd_dhcp_client *client, const uint8_t *addr, + const uint8_t *bcast_addr, size_t addr_len, uint16_t arp_type) { @@ -311,7 +309,9 @@ int sd_dhcp_client_set_mac( return -EINVAL; if (client->mac_addr_len == addr_len && - memcmp(&client->mac_addr, addr, addr_len) == 0) + memcmp(&client->mac_addr, addr, addr_len) == 0 && + (client->bcast_addr_len > 0) == !!bcast_addr && + (!bcast_addr || memcmp(&client->bcast_addr, bcast_addr, addr_len) == 0)) return 0; if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { @@ -323,6 +323,12 @@ int sd_dhcp_client_set_mac( memcpy(&client->mac_addr, addr, addr_len); client->mac_addr_len = addr_len; client->arp_type = arp_type; + client->bcast_addr_len = 0; + + if (bcast_addr) { + memcpy(&client->bcast_addr, bcast_addr, addr_len); + client->bcast_addr_len = addr_len; + } if (need_restart && client->state != DHCP_STATE_STOPPED) { r = sd_dhcp_client_start(client); @@ -543,7 +549,7 @@ int sd_dhcp_client_set_hostname( /* Make sure hostnames qualify as DNS and as Linux hostnames */ if (hostname && - !(hostname_is_valid(hostname, false) && dns_name_is_valid(hostname) > 0)) + !(hostname_is_valid(hostname, 0) && dns_name_is_valid(hostname) > 0)) return -EINVAL; return free_and_strdup(&client->hostname, hostname); @@ -698,7 +704,7 @@ static int client_initialize(sd_dhcp_client *client) { client->receive_message = sd_event_source_unref(client->receive_message); - client->fd = asynchronous_close(client->fd); + client->fd = safe_close(client->fd); (void) event_source_disable(client->timeout_resend); (void) event_source_disable(client->timeout_t1); @@ -730,6 +736,41 @@ static void client_stop(sd_dhcp_client *client, int error) { client_initialize(client); } +/* RFC2131 section 4.1: + * retransmission delays should include -1 to +1 sec of random 'fuzz'. */ +#define RFC2131_RANDOM_FUZZ \ + ((int64_t)(random_u64() % (2 * USEC_PER_SEC)) - (int64_t)USEC_PER_SEC) + +/* RFC2131 section 4.1: + * for retransmission delays, timeout should start at 4s then double + * each attempt with max of 64s, with -1 to +1 sec of random 'fuzz' added. + * This assumes the first call will be using attempt 1. */ +static usec_t client_compute_request_timeout(usec_t now, uint64_t attempt) { + usec_t timeout = (UINT64_C(1) << MIN(attempt + 1, UINT64_C(6))) * USEC_PER_SEC; + + return usec_sub_signed(usec_add(now, timeout), RFC2131_RANDOM_FUZZ); +} + +/* RFC2131 section 4.4.5: + * T1 defaults to (0.5 * duration_of_lease). + * T2 defaults to (0.875 * duration_of_lease). */ +#define T1_DEFAULT(lifetime) ((lifetime) / 2) +#define T2_DEFAULT(lifetime) (((lifetime) * 7) / 8) + +/* RFC2131 section 4.4.5: + * the client SHOULD wait one-half of the remaining time until T2 (in RENEWING state) + * and one-half of the remaining lease time (in REBINDING state), down to a minimum + * of 60 seconds. + * Note that while the default T1/T2 initial times do have random 'fuzz' applied, + * the RFC sec 4.4.5 does not mention adding any fuzz to retries. */ +static usec_t client_compute_reacquisition_timeout(usec_t now, usec_t expire) { + return now + MAX(usec_sub_unsigned(expire, now) / 2, 60 * USEC_PER_SEC); +} + +static int cmp_uint8(const uint8_t *a, const uint8_t *b) { + return CMP(*a, *b); +} + static int client_message_init( sd_dhcp_client *client, DHCPPacket **ret, @@ -840,10 +881,26 @@ static int client_message_init( MAY contain the Parameter Request List option. */ /* NOTE: in case that there would be an option to do not send * any PRL at all, the size should be checked before sending */ - if (client->req_opts_size > 0 && type != DHCP_RELEASE) { + if (!set_isempty(client->req_opts) && type != DHCP_RELEASE) { + _cleanup_free_ uint8_t *opts = NULL; + size_t n_opts, i = 0; + void *val; + + n_opts = set_size(client->req_opts); + opts = new(uint8_t, n_opts); + if (!opts) + return -ENOMEM; + + SET_FOREACH(val, client->req_opts) + opts[i++] = PTR_TO_UINT8(val); + assert(i == n_opts); + + /* For anonymizing the request, let's sort the options. */ + typesafe_qsort(opts, n_opts, cmp_uint8); + r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST, - client->req_opts_size, client->req_opts); + n_opts, opts); if (r < 0) return r; } @@ -1173,9 +1230,8 @@ static int client_timeout_resend( sd_dhcp_client *client = userdata; DHCP_CLIENT_DONT_DESTROY(client); - usec_t next_timeout = 0; + usec_t next_timeout; uint64_t time_now; - uint32_t time_left; int r; assert(s); @@ -1189,22 +1245,11 @@ static int client_timeout_resend( switch (client->state) { case DHCP_STATE_RENEWING: - - time_left = (client->lease->t2 - client->lease->t1) / 2; - if (time_left < 60) - time_left = 60; - - next_timeout = time_now + time_left * USEC_PER_SEC; - + next_timeout = client_compute_reacquisition_timeout(time_now, client->t2_time); break; case DHCP_STATE_REBINDING: - - time_left = (client->lease->lifetime - client->lease->t2) / 2; - if (time_left < 60) - time_left = 60; - - next_timeout = time_now + time_left * USEC_PER_SEC; + next_timeout = client_compute_reacquisition_timeout(time_now, client->expire_time); break; case DHCP_STATE_REBOOTING: @@ -1216,32 +1261,29 @@ static int client_timeout_resend( r = client_start(client); if (r < 0) goto error; - else { - log_dhcp_client(client, "REBOOTED"); - return 0; - } + + log_dhcp_client(client, "REBOOTED"); + return 0; case DHCP_STATE_INIT: case DHCP_STATE_INIT_REBOOT: case DHCP_STATE_SELECTING: case DHCP_STATE_REQUESTING: case DHCP_STATE_BOUND: - - if (client->attempt < client->max_attempts) - client->attempt++; - else + if (client->attempt >= client->max_attempts) goto error; - next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC; - + client->attempt++; + next_timeout = client_compute_request_timeout(time_now, client->attempt); break; case DHCP_STATE_STOPPED: r = -EINVAL; goto error; - } - next_timeout += (random_u32() & 0x1fffff); + default: + assert_not_reached("Unhandled choice"); + } r = event_reset_time(client->event, &client->timeout_resend, clock_boottime_or_monotonic(), @@ -1281,12 +1323,10 @@ static int client_timeout_resend( client->state = DHCP_STATE_REBOOTING; client->request_sent = time_now; - break; case DHCP_STATE_REBOOTING: case DHCP_STATE_BOUND: - break; case DHCP_STATE_STOPPED: @@ -1294,6 +1334,9 @@ static int client_timeout_resend( goto error; } + if (client->attempt >= TRANSIENT_FAILURE_ATTEMPTS) + client_notify(client, SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE); + return 0; error: @@ -1378,9 +1421,10 @@ static int client_start_delayed(sd_dhcp_client *client) { client->xid = random_u32(); - r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, - client->xid, client->mac_addr, - client->mac_addr_len, client->arp_type, client->port); + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, + client->mac_addr, client->mac_addr_len, + client->bcast_addr, client->bcast_addr_len, + client->arp_type, client->port); if (r < 0) { client_stop(client, r); return r; @@ -1423,15 +1467,15 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata) assert(client); client->receive_message = sd_event_source_unref(client->receive_message); - client->fd = asynchronous_close(client->fd); + client->fd = safe_close(client->fd); client->state = DHCP_STATE_REBINDING; client->attempt = 0; - r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, - client->xid, client->mac_addr, - client->mac_addr_len, client->arp_type, - client->port); + r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid, + client->mac_addr, client->mac_addr_len, + client->bcast_addr, client->bcast_addr_len, + client->arp_type, client->port); if (r < 0) { client_stop(client, r); return 0; @@ -1606,25 +1650,8 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack, size_t le return r; } -static uint64_t client_compute_timeout(sd_dhcp_client *client, uint32_t lifetime, double factor) { - assert(client); - assert(client->request_sent); - assert(lifetime > 0); - - if (lifetime > 3) - lifetime -= 3; - else - lifetime = 0; - - return client->request_sent + (lifetime * USEC_PER_SEC * factor) + - + (random_u32() & 0x1fffff); -} - static int client_set_lease_timeouts(sd_dhcp_client *client) { usec_t time_now; - uint64_t lifetime_timeout; - uint64_t t2_timeout; - uint64_t t1_timeout; char time_string[FORMAT_TIMESPAN_MAX]; int r; @@ -1647,93 +1674,76 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) { return r; assert(client->request_sent <= time_now); - /* convert the various timeouts from relative (secs) to absolute (usecs) */ - lifetime_timeout = client_compute_timeout(client, client->lease->lifetime, 1); - if (client->lease->t1 > 0 && client->lease->t2 > 0) { - /* both T1 and T2 are given */ - if (client->lease->t1 < client->lease->t2 && - client->lease->t2 < client->lease->lifetime) { - /* they are both valid */ - t2_timeout = client_compute_timeout(client, client->lease->t2, 1); - t1_timeout = client_compute_timeout(client, client->lease->t1, 1); - } else { - /* discard both */ - t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); - client->lease->t2 = (client->lease->lifetime * 7) / 8; - t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); - client->lease->t1 = client->lease->lifetime / 2; - } - } else if (client->lease->t2 > 0 && client->lease->t2 < client->lease->lifetime) { - /* only T2 is given, and it is valid */ - t2_timeout = client_compute_timeout(client, client->lease->t2, 1); - t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); - client->lease->t1 = client->lease->lifetime / 2; - if (t2_timeout <= t1_timeout) { - /* the computed T1 would be invalid, so discard T2 */ - t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); - client->lease->t2 = (client->lease->lifetime * 7) / 8; - } - } else if (client->lease->t1 > 0 && client->lease->t1 < client->lease->lifetime) { - /* only T1 is given, and it is valid */ - t1_timeout = client_compute_timeout(client, client->lease->t1, 1); - t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); - client->lease->t2 = (client->lease->lifetime * 7) / 8; - if (t2_timeout <= t1_timeout) { - /* the computed T2 would be invalid, so discard T1 */ - t2_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); - client->lease->t2 = client->lease->lifetime / 2; - } - } else { - /* fall back to the default timeouts */ - t1_timeout = client_compute_timeout(client, client->lease->lifetime, 0.5); - client->lease->t1 = client->lease->lifetime / 2; - t2_timeout = client_compute_timeout(client, client->lease->lifetime, 7.0 / 8.0); - client->lease->t2 = (client->lease->lifetime * 7) / 8; - } + /* verify that 0 < t2 < lifetime */ + if (client->lease->t2 == 0 || client->lease->t2 >= client->lease->lifetime) + client->lease->t2 = T2_DEFAULT(client->lease->lifetime); + /* verify that 0 < t1 < lifetime */ + if (client->lease->t1 == 0 || client->lease->t1 >= client->lease->t2) + client->lease->t1 = T1_DEFAULT(client->lease->lifetime); + /* now, if t1 >= t2, t1 *must* be T1_DEFAULT, since the previous check + * could not evalate to false if t1 >= t2; so setting t2 to T2_DEFAULT + * guarantees t1 < t2. */ + if (client->lease->t1 >= client->lease->t2) + client->lease->t2 = T2_DEFAULT(client->lease->lifetime); + + client->expire_time = client->request_sent + client->lease->lifetime * USEC_PER_SEC; + client->t1_time = client->request_sent + client->lease->t1 * USEC_PER_SEC; + client->t2_time = client->request_sent + client->lease->t2 * USEC_PER_SEC; + + /* RFC2131 section 4.4.5: + * Times T1 and T2 SHOULD be chosen with some random "fuzz". + * Since the RFC doesn't specify here the exact 'fuzz' to use, + * we use the range from section 4.1: -1 to +1 sec. */ + client->t1_time = usec_sub_signed(client->t1_time, RFC2131_RANDOM_FUZZ); + client->t2_time = usec_sub_signed(client->t2_time, RFC2131_RANDOM_FUZZ); + + /* after fuzzing, ensure t2 is still >= t1 */ + client->t2_time = MAX(client->t1_time, client->t2_time); /* arm lifetime timeout */ r = event_reset_time(client->event, &client->timeout_expire, clock_boottime_or_monotonic(), - lifetime_timeout, 10 * USEC_PER_MSEC, + client->expire_time, 10 * USEC_PER_MSEC, client_timeout_expire, client, client->event_priority, "dhcp4-lifetime", true); if (r < 0) return r; - log_dhcp_client(client, "lease expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC)); - /* don't arm earlier timeouts if this has already expired */ - if (lifetime_timeout <= time_now) + if (client->expire_time <= time_now) return 0; + log_dhcp_client(client, "lease expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->expire_time - time_now, USEC_PER_SEC)); + /* arm T2 timeout */ r = event_reset_time(client->event, &client->timeout_t2, clock_boottime_or_monotonic(), - t2_timeout, 10 * USEC_PER_MSEC, + client->t2_time, 10 * USEC_PER_MSEC, client_timeout_t2, client, client->event_priority, "dhcp4-t2-timeout", true); if (r < 0) return r; - log_dhcp_client(client, "T2 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC)); - /* don't arm earlier timeout if this has already expired */ - if (t2_timeout <= time_now) + if (client->t2_time <= time_now) return 0; + log_dhcp_client(client, "T2 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t2_time - time_now, USEC_PER_SEC)); + /* arm T1 timeout */ r = event_reset_time(client->event, &client->timeout_t1, clock_boottime_or_monotonic(), - t1_timeout, 10 * USEC_PER_MSEC, + client->t1_time, 10 * USEC_PER_MSEC, client_timeout_t1, client, client->event_priority, "dhcp4-t1-timer", true); if (r < 0) return r; - log_dhcp_client(client, "T1 expires in %s", - format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC)); + if (client->t1_time > time_now) + log_dhcp_client(client, "T1 expires in %s", + format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->t1_time - time_now, USEC_PER_SEC)); return 0; } @@ -1780,7 +1790,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i (void) event_source_disable(client->timeout_resend); client->receive_message = sd_event_source_unref(client->receive_message); - client->fd = asynchronous_close(client->fd); + client->fd = safe_close(client->fd); if (IN_SET(client->state, DHCP_STATE_REQUESTING, DHCP_STATE_REBOOTING)) @@ -1885,12 +1895,11 @@ static int client_receive_message_udp( assert(client); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) { + if (buflen == -ENETDOWN) /* the link is down. Don't return an error or the I/O event source will be disconnected and we won't be able to receive packets again when the link comes back. */ return 0; - } if (buflen < 0) return buflen; @@ -2133,9 +2142,10 @@ int sd_dhcp_client_send_decline(sd_dhcp_client *client) { } int sd_dhcp_client_stop(sd_dhcp_client *client) { - DHCP_CLIENT_DONT_DESTROY(client); + if (!client) + return 0; - assert_return(client, -EINVAL); + DHCP_CLIENT_DONT_DESTROY(client); client_stop(client, SD_DHCP_CLIENT_EVENT_STOP); client->state = DHCP_STATE_STOPPED; @@ -2193,7 +2203,7 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { sd_dhcp_lease_unref(client->lease); - free(client->req_opts); + set_free(client->req_opts); free(client->hostname); free(client->vendor_class_identifier); free(client->mudurl); @@ -2206,6 +2216,10 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) { DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp_client, sd_dhcp_client, dhcp_client_free); int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { + const uint8_t *opts; + size_t n_opts; + int r; + assert_return(ret, -EINVAL); _cleanup_(sd_dhcp_client_unrefp) sd_dhcp_client *client = new(sd_dhcp_client, 1); @@ -2225,14 +2239,18 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) { }; /* NOTE: this could be moved to a function. */ if (anonymize) { - client->req_opts_size = ELEMENTSOF(default_req_opts_anonymize); - client->req_opts = memdup(default_req_opts_anonymize, client->req_opts_size); + n_opts = ELEMENTSOF(default_req_opts_anonymize); + opts = default_req_opts_anonymize; } else { - client->req_opts_size = ELEMENTSOF(default_req_opts); - client->req_opts = memdup(default_req_opts, client->req_opts_size); + n_opts = ELEMENTSOF(default_req_opts); + opts = default_req_opts; + } + + for (size_t i = 0; i < n_opts; i++) { + r = sd_dhcp_client_set_request_option(client, opts[i]); + if (r < 0) + return r; } - if (!client->req_opts) - return -ENOMEM; *ret = TAKE_PTR(client); diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c index c810877c..94b0d35c 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/core/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2013 Intel Corporation. All rights reserved. ***/ @@ -1235,10 +1235,8 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { if (!a) return -ENOMEM; - if (!strv_isempty(a)) { - lease->search_domains = a; - a = NULL; - } + if (!strv_isempty(a)) + lease->search_domains = TAKE_PTR(a); } if (routes) { diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c b/src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c index ec7f1be2..3fafd3c0 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/core/systemd/src/libsystemd-network/sd-dhcp6-client.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014-2015 Intel Corporation. All rights reserved. ***/ @@ -7,7 +7,11 @@ #include <errno.h> #include <sys/ioctl.h> +#if 0 /* NM_IGNORED */ #include <linux/if_arp.h> +#else /* NM_IGNORED */ +#include <net/if_arp.h> +#endif /* NM_IGNORED */ #include <linux/if_infiniband.h> #include "sd-dhcp6-client.h" @@ -23,10 +27,10 @@ #include "hexdecoct.h" #include "hostname-util.h" #include "in-addr-util.h" -#include "network-internal.h" #include "random-util.h" #include "socket-util.h" #include "string-table.h" +#include "strv.h" #include "util.h" #include "web-util.h" @@ -190,8 +194,7 @@ int sd_dhcp6_client_set_mac( assert_return(client, -EINVAL); assert_return(addr, -EINVAL); - assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); - assert_return(arp_type > 0, -EINVAL); + assert_return(addr_len <= MAX_MAC_ADDR_LEN, -EINVAL); assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); @@ -199,8 +202,11 @@ int sd_dhcp6_client_set_mac( assert_return(addr_len == ETH_ALEN, -EINVAL); else if (arp_type == ARPHRD_INFINIBAND) assert_return(addr_len == INFINIBAND_ALEN, -EINVAL); - else - return -EINVAL; + else { + client->arp_type = ARPHRD_NONE; + client->mac_addr_len = 0; + return 0; + } if (client->mac_addr_len == addr_len && memcmp(&client->mac_addr, addr, addr_len) == 0) @@ -411,7 +417,7 @@ int sd_dhcp6_client_set_fqdn( /* Make sure FQDN qualifies as DNS and as Linux hostname */ if (fqdn && - !(hostname_is_valid(fqdn, false) && dns_name_is_valid(fqdn) > 0)) + !(hostname_is_valid(fqdn, 0) && dns_name_is_valid(fqdn) > 0)) return -EINVAL; return free_and_strdup(&client->fqdn, fqdn); @@ -1426,12 +1432,11 @@ static int client_receive_message( assert(client->event); buflen = next_datagram_size_fd(fd); - if (buflen == -ENETDOWN) { + if (buflen == -ENETDOWN) /* the link is down. Don't return an error or the I/O event source will be disconnected and we won't be able to receive packets again when the link comes back. */ return 0; - } if (buflen < 0) return buflen; @@ -1683,7 +1688,8 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) { } int sd_dhcp6_client_stop(sd_dhcp6_client *client) { - assert_return(client, -EINVAL); + if (!client) + return 0; client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP); @@ -1749,8 +1755,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) { } log_dhcp6_client(client, "Started in %s mode", - client->information_request? "Information request": - "Managed"); + client->information_request ? "Information request" : "Managed"); return client_start(client, state); } diff --git a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c b/src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c index 5f5a7fe6..5792f688 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp6-lease.c +++ b/src/core/systemd/src/libsystemd-network/sd-dhcp6-lease.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014-2015 Intel Corporation. All rights reserved. ***/ diff --git a/src/systemd/src/libsystemd-network/sd-ipv4acd.c b/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c index b9e3dce3..096afbd8 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4acd.c +++ b/src/core/systemd/src/libsystemd-network/sd-ipv4acd.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. ***/ @@ -18,10 +18,12 @@ #include "ether-addr-util.h" #include "event-util.h" #include "fd-util.h" +#include "format-util.h" #include "in-addr-util.h" -#include "list.h" +#include "log-link.h" #include "random-util.h" #include "siphash24.h" +#include "string-table.h" #include "string-util.h" #include "time-util.h" @@ -56,6 +58,7 @@ struct sd_ipv4acd { int ifindex; int fd; + char ifname[IF_NAMESIZE + 1]; unsigned n_iteration; unsigned n_conflict; @@ -74,13 +77,30 @@ struct sd_ipv4acd { void* userdata; }; -#define log_ipv4acd_errno(acd, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4ACD: " fmt, ##__VA_ARGS__) -#define log_ipv4acd(acd, fmt, ...) log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) +#define log_ipv4acd_errno(acd, error, fmt, ...) \ + log_interface_full_errno(sd_ipv4acd_get_ifname(acd), LOG_DEBUG, error, "IPV4ACD: " fmt, ##__VA_ARGS__) +#define log_ipv4acd(acd, fmt, ...) \ + log_ipv4acd_errno(acd, 0, fmt, ##__VA_ARGS__) + +static const char * const ipv4acd_state_table[_IPV4ACD_STATE_MAX] = { + [IPV4ACD_STATE_INIT] = "init", + [IPV4ACD_STATE_STARTED] = "started", + [IPV4ACD_STATE_WAITING_PROBE] = "waiting-probe", + [IPV4ACD_STATE_PROBING] = "probing", + [IPV4ACD_STATE_WAITING_ANNOUNCE] = "waiting-announce", + [IPV4ACD_STATE_ANNOUNCING] = "announcing", + [IPV4ACD_STATE_RUNNING] = "running", +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(ipv4acd_state, IPv4ACDState); static void ipv4acd_set_state(sd_ipv4acd *acd, IPv4ACDState st, bool reset_counter) { assert(acd); assert(st < _IPV4ACD_STATE_MAX); + if (st != acd->state) + log_ipv4acd(acd, "%s -> %s", ipv4acd_state_to_string(acd->state), ipv4acd_state_to_string(st)); + if (st == acd->state && !reset_counter) acd->n_iteration++; else { @@ -146,7 +166,8 @@ static void ipv4acd_client_notify(sd_ipv4acd *acd, int event) { int sd_ipv4acd_stop(sd_ipv4acd *acd) { IPv4ACDState old_state; - assert_return(acd, -EINVAL); + if (!acd) + return 0; old_state = acd->state; @@ -379,15 +400,35 @@ fail: } int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int ifindex) { + char ifname[IF_NAMESIZE + 1]; + assert_return(acd, -EINVAL); assert_return(ifindex > 0, -EINVAL); assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY); + if (!format_ifname(ifindex, ifname)) + return -ENODEV; + + strcpy(acd->ifname, ifname); acd->ifindex = ifindex; return 0; } +int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd) { + if (!acd) + return -EINVAL; + + return acd->ifindex; +} + +const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd) { + if (!acd) + return NULL; + + return empty_to_null(acd->ifname); +} + int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr) { assert_return(acd, -EINVAL); assert_return(addr, -EINVAL); diff --git a/src/systemd/src/libsystemd-network/sd-ipv4ll.c b/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c index 0bfaf265..c5e7a91f 100644 --- a/src/systemd/src/libsystemd-network/sd-ipv4ll.c +++ b/src/core/systemd/src/libsystemd-network/sd-ipv4ll.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /*** Copyright © 2014 Axis Communications AB. All rights reserved. ***/ @@ -17,7 +17,7 @@ #include "alloc-util.h" #include "ether-addr-util.h" #include "in-addr-util.h" -#include "list.h" +#include "log-link.h" #include "random-util.h" #include "siphash24.h" #include "sparse-endian.h" @@ -51,8 +51,10 @@ struct sd_ipv4ll { void* userdata; }; -#define log_ipv4ll_errno(ll, error, fmt, ...) log_internal(LOG_DEBUG, error, PROJECT_FILE, __LINE__, __func__, "IPV4LL: " fmt, ##__VA_ARGS__) -#define log_ipv4ll(ll, fmt, ...) log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) +#define log_ipv4ll_errno(ll, error, fmt, ...) \ + log_interface_full_errno(sd_ipv4ll_get_ifname(ll), LOG_DEBUG, error, "IPV4LL: " fmt, ##__VA_ARGS__) +#define log_ipv4ll(ll, fmt, ...) \ + log_ipv4ll_errno(ll, 0, fmt, ##__VA_ARGS__) static void ipv4ll_on_acd(sd_ipv4acd *ll, int event, void *userdata); @@ -91,7 +93,8 @@ int sd_ipv4ll_new(sd_ipv4ll **ret) { } int sd_ipv4ll_stop(sd_ipv4ll *ll) { - assert_return(ll, -EINVAL); + if (!ll) + return 0; return sd_ipv4acd_stop(ll->acd); } @@ -104,6 +107,20 @@ int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int ifindex) { return sd_ipv4acd_set_ifindex(ll->acd, ifindex); } +int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll) { + if (!ll) + return -EINVAL; + + return sd_ipv4acd_get_ifindex(ll->acd); +} + +const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll) { + if (!ll) + return NULL; + + return sd_ipv4acd_get_ifname(ll->acd); +} + int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr) { int r; diff --git a/src/systemd/src/libsystemd-network/sd-lldp.c b/src/core/systemd/src/libsystemd-network/sd-lldp.c index 524b1bab..b12d8e27 100644 --- a/src/systemd/src/libsystemd-network/sd-lldp.c +++ b/src/core/systemd/src/libsystemd-network/sd-lldp.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" @@ -278,7 +278,8 @@ fail: } _public_ int sd_lldp_stop(sd_lldp *lldp) { - assert_return(lldp, -EINVAL); + if (!lldp) + return 0; if (lldp->fd < 0) return 0; diff --git a/src/systemd/src/libsystemd/sd-event/event-source.h b/src/core/systemd/src/libsystemd/sd-event/event-source.h index 08eb9b6a..f0d2a1b9 100644 --- a/src/systemd/src/libsystemd/sd-event/event-source.h +++ b/src/core/systemd/src/libsystemd/sd-event/event-source.h @@ -1,5 +1,5 @@ #pragma once -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include <sys/epoll.h> #include <sys/timerfd.h> @@ -11,6 +11,7 @@ #include "hashmap.h" #include "list.h" #include "prioq.h" +#include "ratelimit.h" typedef enum EventSourceType { SOURCE_IO, @@ -60,6 +61,8 @@ struct sd_event_source { bool pending:1; bool dispatching:1; bool floating:1; + bool exit_on_failure:1; + bool ratelimited:1; int64_t priority; unsigned pending_index; @@ -71,6 +74,13 @@ struct sd_event_source { LIST_FIELDS(sd_event_source, sources); + RateLimit rate_limit; + + /* These are primarily fields relevant for time event sources, but since any event source can + * effectively become one when rate-limited, this is part of the common fields. */ + unsigned earliest_index; + unsigned latest_index; + union { struct { sd_event_io_handler_t callback; @@ -83,8 +93,6 @@ struct sd_event_source { struct { sd_event_time_handler_t callback; usec_t next, accuracy; - unsigned earliest_index; - unsigned latest_index; } time; struct { sd_event_signal_handler_t callback; diff --git a/src/systemd/src/libsystemd/sd-event/event-util.c b/src/core/systemd/src/libsystemd/sd-event/event-util.c index e8384cfd..7cc55be1 100644 --- a/src/systemd/src/libsystemd/sd-event/event-util.c +++ b/src/core/systemd/src/libsystemd/sd-event/event-util.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" diff --git a/src/systemd/src/libsystemd/sd-event/event-util.h b/src/core/systemd/src/libsystemd/sd-event/event-util.h index 00180955..c8f97bc8 100644 --- a/src/systemd/src/libsystemd/sd-event/event-util.h +++ b/src/core/systemd/src/libsystemd/sd-event/event-util.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include <stdbool.h> diff --git a/src/systemd/src/libsystemd/sd-event/sd-event.c b/src/core/systemd/src/libsystemd/sd-event/sd-event.c index d5993a22..dda4be00 100644 --- a/src/systemd/src/libsystemd/sd-event/sd-event.c +++ b/src/core/systemd/src/libsystemd/sd-event/sd-event.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" @@ -39,6 +39,16 @@ static bool EVENT_SOURCE_WATCH_PIDFD(sd_event_source *s) { s->child.options == WEXITED; } +static bool event_source_is_online(sd_event_source *s) { + assert(s); + return s->enabled != SD_EVENT_OFF && !s->ratelimited; +} + +static bool event_source_is_offline(sd_event_source *s) { + assert(s); + return s->enabled == SD_EVENT_OFF || s->ratelimited; +} + static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] = { [SOURCE_IO] = "io", [SOURCE_TIME_REALTIME] = "realtime", @@ -57,7 +67,25 @@ static const char* const event_source_type_table[_SOURCE_EVENT_SOURCE_TYPE_MAX] DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(event_source_type, int); -#define EVENT_SOURCE_IS_TIME(t) IN_SET((t), SOURCE_TIME_REALTIME, SOURCE_TIME_BOOTTIME, SOURCE_TIME_MONOTONIC, SOURCE_TIME_REALTIME_ALARM, SOURCE_TIME_BOOTTIME_ALARM) +#define EVENT_SOURCE_IS_TIME(t) \ + IN_SET((t), \ + SOURCE_TIME_REALTIME, \ + SOURCE_TIME_BOOTTIME, \ + SOURCE_TIME_MONOTONIC, \ + SOURCE_TIME_REALTIME_ALARM, \ + SOURCE_TIME_BOOTTIME_ALARM) + +#define EVENT_SOURCE_CAN_RATE_LIMIT(t) \ + IN_SET((t), \ + SOURCE_IO, \ + SOURCE_TIME_REALTIME, \ + SOURCE_TIME_BOOTTIME, \ + SOURCE_TIME_MONOTONIC, \ + SOURCE_TIME_REALTIME_ALARM, \ + SOURCE_TIME_BOOTTIME_ALARM, \ + SOURCE_SIGNAL, \ + SOURCE_DEFER, \ + SOURCE_INOTIFY) struct sd_event { unsigned n_ref; @@ -83,7 +111,7 @@ struct sd_event { Hashmap *signal_data; /* indexed by priority */ Hashmap *child_sources; - unsigned n_enabled_child_sources; + unsigned n_online_child_sources; Set *post_sources; @@ -122,7 +150,7 @@ struct sd_event { LIST_HEAD(sd_event_source, sources); - usec_t last_run, last_log; + usec_t last_run_usec, last_log_usec; unsigned delays[sizeof(usec_t) * 8]; }; @@ -148,6 +176,11 @@ static int pending_prioq_compare(const void *a, const void *b) { if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; + /* Non rate-limited ones first. */ + r = CMP(!!x->ratelimited, !!y->ratelimited); + if (r != 0) + return r; + /* Lower priority values first */ r = CMP(x->priority, y->priority); if (r != 0) @@ -170,6 +203,11 @@ static int prepare_prioq_compare(const void *a, const void *b) { if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) return 1; + /* Non rate-limited ones first. */ + r = CMP(!!x->ratelimited, !!y->ratelimited); + if (r != 0) + return r; + /* Move most recently prepared ones last, so that we can stop * preparing as soon as we hit one that has already been * prepared in the current iteration */ @@ -181,12 +219,30 @@ static int prepare_prioq_compare(const void *a, const void *b) { return CMP(x->priority, y->priority); } +static usec_t time_event_source_next(const sd_event_source *s) { + assert(s); + + /* We have two kinds of event sources that have elapsation times associated with them: the actual + * time based ones and the ones for which a ratelimit can be in effect (where we want to be notified + * once the ratelimit time window ends). Let's return the next elapsing time depending on what we are + * looking at here. */ + + if (s->ratelimited) { /* If rate-limited the next elapsation is when the ratelimit time window ends */ + assert(s->rate_limit.begin != 0); + assert(s->rate_limit.interval != 0); + return usec_add(s->rate_limit.begin, s->rate_limit.interval); + } + + /* Otherwise this must be a time event source, if not ratelimited */ + if (EVENT_SOURCE_IS_TIME(s->type)) + return s->time.next; + + return USEC_INFINITY; +} + static int earliest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; - assert(EVENT_SOURCE_IS_TIME(x->type)); - assert(x->type == y->type); - /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; @@ -200,19 +256,30 @@ static int earliest_time_prioq_compare(const void *a, const void *b) { return 1; /* Order by time */ - return CMP(x->time.next, y->time.next); + return CMP(time_event_source_next(x), time_event_source_next(y)); } static usec_t time_event_source_latest(const sd_event_source *s) { - return usec_add(s->time.next, s->time.accuracy); + assert(s); + + if (s->ratelimited) { /* For ratelimited stuff the earliest and the latest time shall actually be the + * same, as we should avoid adding additional inaccuracy on an inaccuracy time + * window */ + assert(s->rate_limit.begin != 0); + assert(s->rate_limit.interval != 0); + return usec_add(s->rate_limit.begin, s->rate_limit.interval); + } + + /* Must be a time event source, if not ratelimited */ + if (EVENT_SOURCE_IS_TIME(s->type)) + return usec_add(s->time.next, s->time.accuracy); + + return USEC_INFINITY; } static int latest_time_prioq_compare(const void *a, const void *b) { const sd_event_source *x = a, *y = b; - assert(EVENT_SOURCE_IS_TIME(x->type)); - assert(x->type == y->type); - /* Enabled ones first */ if (x->enabled != SD_EVENT_OFF && y->enabled == SD_EVENT_OFF) return -1; @@ -382,7 +449,7 @@ static void source_io_unregister(sd_event_source *s) { return; if (epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->io.fd, NULL) < 0) - log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", + log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll, ignoring: %m", strna(s->description), event_source_type_to_string(s->type)); s->io.registered = false; @@ -401,13 +468,10 @@ static int source_io_register( .events = events | (enabled == SD_EVENT_ONESHOT ? EPOLLONESHOT : 0), .data.ptr = s, }; - int r; - r = epoll_ctl(s->event->epoll_fd, + if (epoll_ctl(s->event->epoll_fd, s->io.registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, - s->io.fd, - &ev); - if (r < 0) + s->io.fd, &ev) < 0) return -errno; s->io.registered = true; @@ -427,15 +491,13 @@ static void source_child_pidfd_unregister(sd_event_source *s) { if (EVENT_SOURCE_WATCH_PIDFD(s)) if (epoll_ctl(s->event->epoll_fd, EPOLL_CTL_DEL, s->child.pidfd, NULL) < 0) - log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll: %m", + log_debug_errno(errno, "Failed to remove source %s (type %s) from epoll, ignoring: %m", strna(s->description), event_source_type_to_string(s->type)); s->child.registered = false; } static int source_child_pidfd_register(sd_event_source *s, int enabled) { - int r; - assert(s); assert(s->type == SOURCE_CHILD); assert(enabled != SD_EVENT_OFF); @@ -446,11 +508,9 @@ static int source_child_pidfd_register(sd_event_source *s, int enabled) { .data.ptr = s, }; - if (s->child.registered) - r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_MOD, s->child.pidfd, &ev); - else - r = epoll_ctl(s->event->epoll_fd, EPOLL_CTL_ADD, s->child.pidfd, &ev); - if (r < 0) + if (epoll_ctl(s->event->epoll_fd, + s->child.registered ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, + s->child.pidfd, &ev) < 0) return -errno; } @@ -618,8 +678,7 @@ static int event_make_signal_data( .data.ptr = d, }; - r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev); - if (r < 0) { + if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, d->fd, &ev) < 0) { r = -errno; goto fail; } @@ -671,12 +730,12 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) * and possibly drop the signalfd for it. */ if (sig == SIGCHLD && - e->n_enabled_child_sources > 0) + e->n_online_child_sources > 0) return; if (e->signal_sources && e->signal_sources[sig] && - e->signal_sources[sig]->enabled != SD_EVENT_OFF) + event_source_is_online(e->signal_sources[sig])) return; /* @@ -706,6 +765,52 @@ static void event_gc_signal_data(sd_event *e, const int64_t *priority, int sig) event_unmask_signal_data(e, d, sig); } +static void event_source_pp_prioq_reshuffle(sd_event_source *s) { + assert(s); + + /* Reshuffles the pending + prepare prioqs. Called whenever the dispatch order changes, i.e. when + * they are enabled/disabled or marked pending and such. */ + + if (s->pending) + prioq_reshuffle(s->event->pending, s, &s->pending_index); + + if (s->prepare) + prioq_reshuffle(s->event->prepare, s, &s->prepare_index); +} + +static void event_source_time_prioq_reshuffle(sd_event_source *s) { + struct clock_data *d; + + assert(s); + + /* Called whenever the event source's timer ordering properties changed, i.e. time, accuracy, + * pending, enable state. Makes sure the two prioq's are ordered properly again. */ + + if (s->ratelimited) + d = &s->event->monotonic; + else { + assert(EVENT_SOURCE_IS_TIME(s->type)); + assert_se(d = event_get_clock_data(s->event, s->type)); + } + + prioq_reshuffle(d->earliest, s, &s->earliest_index); + prioq_reshuffle(d->latest, s, &s->latest_index); + d->needs_rearm = true; +} + +static void event_source_time_prioq_remove( + sd_event_source *s, + struct clock_data *d) { + + assert(s); + assert(d); + + prioq_remove(d->earliest, s, &s->earliest_index); + prioq_remove(d->latest, s, &s->latest_index); + s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; + d->needs_rearm = true; +} + static void source_disconnect(sd_event_source *s) { sd_event *event; @@ -728,17 +833,18 @@ static void source_disconnect(sd_event_source *s) { case SOURCE_TIME_BOOTTIME: case SOURCE_TIME_MONOTONIC: case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: { - struct clock_data *d; + case SOURCE_TIME_BOOTTIME_ALARM: + /* Only remove this event source from the time event source here if it is not ratelimited. If + * it is ratelimited, we'll remove it below, separately. Why? Because the clock used might + * differ: ratelimiting always uses CLOCK_MONOTONIC, but timer events might use any clock */ - d = event_get_clock_data(s->event, s->type); - assert(d); + if (!s->ratelimited) { + struct clock_data *d; + assert_se(d = event_get_clock_data(s->event, s->type)); + event_source_time_prioq_remove(s, d); + } - prioq_remove(d->earliest, s, &s->time.earliest_index); - prioq_remove(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; break; - } case SOURCE_SIGNAL: if (s->signal.sig > 0) { @@ -753,9 +859,9 @@ static void source_disconnect(sd_event_source *s) { case SOURCE_CHILD: if (s->child.pid > 0) { - if (s->enabled != SD_EVENT_OFF) { - assert(s->event->n_enabled_child_sources > 0); - s->event->n_enabled_child_sources--; + if (event_source_is_online(s)) { + assert(s->event->n_online_child_sources > 0); + s->event->n_online_child_sources--; } (void) hashmap_remove(s->event->child_sources, PID_TO_PTR(s->child.pid)); @@ -825,6 +931,9 @@ static void source_disconnect(sd_event_source *s) { if (s->prepare) prioq_remove(s->event->prepare, s, &s->prepare_index); + if (s->ratelimited) + event_source_time_prioq_remove(s, &s->event->monotonic); + event = TAKE_PTR(s->event); LIST_REMOVE(sources, event->sources, s); event->n_sources--; @@ -912,16 +1021,8 @@ static int source_set_pending(sd_event_source *s, bool b) { } else assert_se(prioq_remove(s->event->pending, s, &s->pending_index)); - if (EVENT_SOURCE_IS_TIME(s->type)) { - struct clock_data *d; - - d = event_get_clock_data(s->event, s->type); - assert(d); - - prioq_reshuffle(d->earliest, s, &s->time.earliest_index); - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; - } + if (EVENT_SOURCE_IS_TIME(s->type)) + event_source_time_prioq_reshuffle(s); if (s->type == SOURCE_SIGNAL && !b) { struct signal_data *d; @@ -974,6 +1075,12 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t return s; } +static int io_exit_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + _public_ int sd_event_add_io( sd_event *e, sd_event_source **ret, @@ -989,10 +1096,12 @@ _public_ int sd_event_add_io( assert_return(e = event_resolve(e), -ENOPKG); assert_return(fd >= 0, -EBADF); assert_return(!(events & ~(EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLPRI|EPOLLERR|EPOLLHUP|EPOLLET)), -EINVAL); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (!callback) + callback = io_exit_callback; + s = source_new(e, !ret, SOURCE_IO); if (!s) return -ENOMEM; @@ -1046,7 +1155,6 @@ static int event_setup_timer_fd( return 0; _cleanup_close_ int fd = -1; - int r; fd = timerfd_create(clock, TFD_NONBLOCK|TFD_CLOEXEC); if (fd < 0) @@ -1059,8 +1167,7 @@ static int event_setup_timer_fd( .data.ptr = d, }; - r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev); - if (r < 0) + if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) return -errno; d->fd = TAKE_FD(fd); @@ -1073,6 +1180,52 @@ static int time_exit_callback(sd_event_source *s, uint64_t usec, void *userdata) return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); } +static int setup_clock_data(sd_event *e, struct clock_data *d, clockid_t clock) { + int r; + + assert(d); + + if (d->fd < 0) { + r = event_setup_timer_fd(e, d, clock); + if (r < 0) + return r; + } + + r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); + if (r < 0) + return r; + + r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); + if (r < 0) + return r; + + return 0; +} + +static int event_source_time_prioq_put( + sd_event_source *s, + struct clock_data *d) { + + int r; + + assert(s); + assert(d); + + r = prioq_put(d->earliest, s, &s->earliest_index); + if (r < 0) + return r; + + r = prioq_put(d->latest, s, &s->latest_index); + if (r < 0) { + assert_se(prioq_remove(d->earliest, s, &s->earliest_index) > 0); + s->earliest_index = PRIOQ_IDX_NULL; + return r; + } + + d->needs_rearm = true; + return 0; +} + _public_ int sd_event_add_time( sd_event *e, sd_event_source **ret, @@ -1103,23 +1256,12 @@ _public_ int sd_event_add_time( if (!callback) callback = time_exit_callback; - d = event_get_clock_data(e, type); - assert(d); - - r = prioq_ensure_allocated(&d->earliest, earliest_time_prioq_compare); - if (r < 0) - return r; + assert_se(d = event_get_clock_data(e, type)); - r = prioq_ensure_allocated(&d->latest, latest_time_prioq_compare); + r = setup_clock_data(e, d, clock); if (r < 0) return r; - if (d->fd < 0) { - r = event_setup_timer_fd(e, d, clock); - if (r < 0) - return r; - } - s = source_new(e, !ret, type); if (!s) return -ENOMEM; @@ -1127,17 +1269,11 @@ _public_ int sd_event_add_time( s->time.next = usec; s->time.accuracy = accuracy == 0 ? DEFAULT_ACCURACY_USEC : accuracy; s->time.callback = callback; - s->time.earliest_index = s->time.latest_index = PRIOQ_IDX_NULL; + s->earliest_index = s->latest_index = PRIOQ_IDX_NULL; s->userdata = userdata; s->enabled = SD_EVENT_ONESHOT; - d->needs_rearm = true; - - r = prioq_put(d->earliest, s, &s->time.earliest_index); - if (r < 0) - return r; - - r = prioq_put(d->latest, s, &s->time.latest_index); + r = event_source_time_prioq_put(s, d); if (r < 0) return r; @@ -1238,6 +1374,12 @@ _public_ int sd_event_add_signal( return 0; } +static int child_exit_callback(sd_event_source *s, const siginfo_t *si, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + static bool shall_use_pidfd(void) { /* Mostly relevant for debugging, i.e. this is used in test-event.c to test the event loop once with and once without pidfd */ return getenv_bool_secure("SYSTEMD_PIDFD") != 0; @@ -1259,11 +1401,13 @@ _public_ int sd_event_add_child( assert_return(pid > 1, -EINVAL); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); assert_return(options != 0, -EINVAL); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); - if (e->n_enabled_child_sources == 0) { + if (!callback) + callback = child_exit_callback; + + if (e->n_online_child_sources == 0) { /* Caller must block SIGCHLD before using us to watch children, even if pidfd is available, * for compatibility with pre-pidfd and because we don't want the reap the child processes * ourselves, i.e. call waitid(), and don't want Linux' default internal logic for that to @@ -1313,31 +1457,25 @@ _public_ int sd_event_add_child( if (r < 0) return r; - e->n_enabled_child_sources++; - if (EVENT_SOURCE_WATCH_PIDFD(s)) { /* We have a pidfd and we only want to watch for exit */ - r = source_child_pidfd_register(s, s->enabled); - if (r < 0) { - e->n_enabled_child_sources--; + if (r < 0) return r; - } + } else { /* We have no pidfd or we shall wait for some other event than WEXITED */ - r = event_make_signal_data(e, SIGCHLD, NULL); - if (r < 0) { - e->n_enabled_child_sources--; + if (r < 0) return r; - } e->need_process_child = true; } + e->n_online_child_sources++; + if (ret) *ret = s; - TAKE_PTR(s); return 0; } @@ -1360,11 +1498,13 @@ _public_ int sd_event_add_child_pidfd( assert_return(pidfd >= 0, -EBADF); assert_return(!(options & ~(WEXITED|WSTOPPED|WCONTINUED)), -EINVAL); assert_return(options != 0, -EINVAL); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); - if (e->n_enabled_child_sources == 0) { + if (!callback) + callback = child_exit_callback; + + if (e->n_online_child_sources == 0) { r = signal_is_blocked(SIGCHLD); if (r < 0) return r; @@ -1400,36 +1540,35 @@ _public_ int sd_event_add_child_pidfd( if (r < 0) return r; - e->n_enabled_child_sources++; - if (EVENT_SOURCE_WATCH_PIDFD(s)) { /* We only want to watch for WEXITED */ - r = source_child_pidfd_register(s, s->enabled); - if (r < 0) { - e->n_enabled_child_sources--; + if (r < 0) return r; - } } else { /* We shall wait for some other event than WEXITED */ - r = event_make_signal_data(e, SIGCHLD, NULL); - if (r < 0) { - e->n_enabled_child_sources--; + if (r < 0) return r; - } e->need_process_child = true; } + e->n_online_child_sources++; + if (ret) *ret = s; - TAKE_PTR(s); return 0; } #endif /* NM_IGNORED */ +static int generic_exit_callback(sd_event_source *s, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + _public_ int sd_event_add_defer( sd_event *e, sd_event_source **ret, @@ -1441,10 +1580,12 @@ _public_ int sd_event_add_defer( assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (!callback) + callback = generic_exit_callback; + s = source_new(e, !ret, SOURCE_DEFER); if (!s) return -ENOMEM; @@ -1475,10 +1616,12 @@ _public_ int sd_event_add_post( assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (!callback) + callback = generic_exit_callback; + s = source_new(e, !ret, SOURCE_POST); if (!s) return -ENOMEM; @@ -1830,6 +1973,12 @@ static int inode_data_realize_watch(sd_event *e, struct inode_data *d) { return 1; } +static int inotify_exit_callback(sd_event_source *s, const struct inotify_event *event, void *userdata) { + assert(s); + + return sd_event_exit(sd_event_source_get_event(s), PTR_TO_INT(userdata)); +} + _public_ int sd_event_add_inotify( sd_event *e, sd_event_source **ret, @@ -1848,10 +1997,12 @@ _public_ int sd_event_add_inotify( assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); assert_return(path, -EINVAL); - assert_return(callback, -EINVAL); assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(!event_pid_changed(e), -ECHILD); + if (!callback) + callback = inotify_exit_callback; + /* Refuse IN_MASK_ADD since we coalesce watches on the same inode, and hence really don't want to merge * masks. Or in other words, this whole code exists only to manage IN_MASK_ADD type operations for you, hence * the user can't use them for us. */ @@ -1990,7 +2141,7 @@ _public_ int sd_event_source_set_io_fd(sd_event_source *s, int fd) { if (s->io.fd == fd) return 0; - if (s->enabled == SD_EVENT_OFF) { + if (event_source_is_offline(s)) { s->io.fd = fd; s->io.registered = false; } else { @@ -2057,7 +2208,7 @@ _public_ int sd_event_source_set_io_events(sd_event_source *s, uint32_t events) if (r < 0) return r; - if (s->enabled != SD_EVENT_OFF) { + if (event_source_is_online(s)) { r = source_io_register(s, s->enabled, events); if (r < 0) return r; @@ -2160,7 +2311,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) event_gc_inode_data(s->event, old_inode_data); - } else if (s->type == SOURCE_SIGNAL && s->enabled != SD_EVENT_OFF) { + } else if (s->type == SOURCE_SIGNAL && event_source_is_online(s)) { struct signal_data *old, *d; /* Move us from the signalfd belonging to the old @@ -2180,11 +2331,7 @@ _public_ int sd_event_source_set_priority(sd_event_source *s, int64_t priority) } else s->priority = priority; - if (s->pending) - prioq_reshuffle(s->event->pending, s, &s->pending_index); - - if (s->prepare) - prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + event_source_pp_prioq_reshuffle(s); if (s->type == SOURCE_EXIT) prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); @@ -2201,198 +2348,222 @@ fail: return r; } -_public_ int sd_event_source_get_enabled(sd_event_source *s, int *m) { +_public_ int sd_event_source_get_enabled(sd_event_source *s, int *ret) { assert_return(s, -EINVAL); assert_return(!event_pid_changed(s->event), -ECHILD); - if (m) - *m = s->enabled; + if (ret) + *ret = s->enabled; + return s->enabled != SD_EVENT_OFF; } -_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { +static int event_source_offline( + sd_event_source *s, + int enabled, + bool ratelimited) { + + bool was_offline; int r; - assert_return(s, -EINVAL); - assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); - assert_return(!event_pid_changed(s->event), -ECHILD); + assert(s); + assert(enabled == SD_EVENT_OFF || ratelimited); - /* If we are dead anyway, we are fine with turning off - * sources, but everything else needs to fail. */ - if (s->event->state == SD_EVENT_FINISHED) - return m == SD_EVENT_OFF ? 0 : -ESTALE; + /* Unset the pending flag when this event source is disabled */ + if (s->enabled != SD_EVENT_OFF && + enabled == SD_EVENT_OFF && + !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } - if (s->enabled == m) - return 0; + was_offline = event_source_is_offline(s); + s->enabled = enabled; + s->ratelimited = ratelimited; - if (m == SD_EVENT_OFF) { + switch (s->type) { - /* Unset the pending flag when this event source is disabled */ - if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { - r = source_set_pending(s, false); - if (r < 0) - return r; - } + case SOURCE_IO: + source_io_unregister(s); + break; - switch (s->type) { + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: + event_source_time_prioq_reshuffle(s); + break; - case SOURCE_IO: - source_io_unregister(s); - s->enabled = m; - break; + case SOURCE_SIGNAL: + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + break; - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: { - struct clock_data *d; + case SOURCE_CHILD: + if (!was_offline) { + assert(s->event->n_online_child_sources > 0); + s->event->n_online_child_sources--; + } - s->enabled = m; - d = event_get_clock_data(s->event, s->type); - assert(d); + if (EVENT_SOURCE_WATCH_PIDFD(s)) + source_child_pidfd_unregister(s); + else + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + break; - prioq_reshuffle(d->earliest, s, &s->time.earliest_index); - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; - break; - } + case SOURCE_EXIT: + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; - case SOURCE_SIGNAL: - s->enabled = m; + case SOURCE_DEFER: + case SOURCE_POST: + case SOURCE_INOTIFY: + break; - event_gc_signal_data(s->event, &s->priority, s->signal.sig); - break; + default: + assert_not_reached("Wut? I shouldn't exist."); + } - case SOURCE_CHILD: - s->enabled = m; + return 1; +} - assert(s->event->n_enabled_child_sources > 0); - s->event->n_enabled_child_sources--; +static int event_source_online( + sd_event_source *s, + int enabled, + bool ratelimited) { - if (EVENT_SOURCE_WATCH_PIDFD(s)) - source_child_pidfd_unregister(s); - else - event_gc_signal_data(s->event, &s->priority, SIGCHLD); + bool was_online; + int r; - break; + assert(s); + assert(enabled != SD_EVENT_OFF || !ratelimited); - case SOURCE_EXIT: - s->enabled = m; - prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); - break; + /* Unset the pending flag when this event source is enabled */ + if (s->enabled == SD_EVENT_OFF && + enabled != SD_EVENT_OFF && + !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { + r = source_set_pending(s, false); + if (r < 0) + return r; + } - case SOURCE_DEFER: - case SOURCE_POST: - case SOURCE_INOTIFY: - s->enabled = m; - break; + /* Are we really ready for onlining? */ + if (enabled == SD_EVENT_OFF || ratelimited) { + /* Nope, we are not ready for onlining, then just update the precise state and exit */ + s->enabled = enabled; + s->ratelimited = ratelimited; + return 0; + } - default: - assert_not_reached("Wut? I shouldn't exist."); - } + was_online = event_source_is_online(s); - } else { + switch (s->type) { + case SOURCE_IO: + r = source_io_register(s, enabled, s->io.events); + if (r < 0) + return r; + break; - /* Unset the pending flag when this event source is enabled */ - if (s->enabled == SD_EVENT_OFF && !IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { - r = source_set_pending(s, false); - if (r < 0) - return r; + case SOURCE_SIGNAL: + r = event_make_signal_data(s->event, s->signal.sig, NULL); + if (r < 0) { + event_gc_signal_data(s->event, &s->priority, s->signal.sig); + return r; } - switch (s->type) { + break; + + case SOURCE_CHILD: + if (EVENT_SOURCE_WATCH_PIDFD(s)) { + /* yes, we have pidfd */ - case SOURCE_IO: - r = source_io_register(s, m, s->io.events); + r = source_child_pidfd_register(s, enabled); if (r < 0) return r; + } else { + /* no pidfd, or something other to watch for than WEXITED */ - s->enabled = m; - break; - - case SOURCE_TIME_REALTIME: - case SOURCE_TIME_BOOTTIME: - case SOURCE_TIME_MONOTONIC: - case SOURCE_TIME_REALTIME_ALARM: - case SOURCE_TIME_BOOTTIME_ALARM: { - struct clock_data *d; - - s->enabled = m; - d = event_get_clock_data(s->event, s->type); - assert(d); - - prioq_reshuffle(d->earliest, s, &s->time.earliest_index); - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; - break; + r = event_make_signal_data(s->event, SIGCHLD, NULL); + if (r < 0) { + event_gc_signal_data(s->event, &s->priority, SIGCHLD); + return r; + } } - case SOURCE_SIGNAL: + if (!was_online) + s->event->n_online_child_sources++; + break; - s->enabled = m; + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: + case SOURCE_EXIT: + case SOURCE_DEFER: + case SOURCE_POST: + case SOURCE_INOTIFY: + break; - r = event_make_signal_data(s->event, s->signal.sig, NULL); - if (r < 0) { - s->enabled = SD_EVENT_OFF; - event_gc_signal_data(s->event, &s->priority, s->signal.sig); - return r; - } + default: + assert_not_reached("Wut? I shouldn't exist."); + } - break; + s->enabled = enabled; + s->ratelimited = ratelimited; - case SOURCE_CHILD: + /* Non-failing operations below */ + switch (s->type) { + case SOURCE_TIME_REALTIME: + case SOURCE_TIME_BOOTTIME: + case SOURCE_TIME_MONOTONIC: + case SOURCE_TIME_REALTIME_ALARM: + case SOURCE_TIME_BOOTTIME_ALARM: + event_source_time_prioq_reshuffle(s); + break; - if (s->enabled == SD_EVENT_OFF) - s->event->n_enabled_child_sources++; + case SOURCE_EXIT: + prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); + break; - s->enabled = m; + default: + break; + } - if (EVENT_SOURCE_WATCH_PIDFD(s)) { - /* yes, we have pidfd */ + return 1; +} - r = source_child_pidfd_register(s, s->enabled); - if (r < 0) { - s->enabled = SD_EVENT_OFF; - s->event->n_enabled_child_sources--; - return r; - } - } else { - /* no pidfd, or something other to watch for than WEXITED */ +_public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + int r; - r = event_make_signal_data(s->event, SIGCHLD, NULL); - if (r < 0) { - s->enabled = SD_EVENT_OFF; - s->event->n_enabled_child_sources--; - event_gc_signal_data(s->event, &s->priority, SIGCHLD); - return r; - } - } + assert_return(s, -EINVAL); + assert_return(IN_SET(m, SD_EVENT_OFF, SD_EVENT_ON, SD_EVENT_ONESHOT), -EINVAL); + assert_return(!event_pid_changed(s->event), -ECHILD); - break; + /* If we are dead anyway, we are fine with turning off sources, but everything else needs to fail. */ + if (s->event->state == SD_EVENT_FINISHED) + return m == SD_EVENT_OFF ? 0 : -ESTALE; - case SOURCE_EXIT: - s->enabled = m; - prioq_reshuffle(s->event->exit, s, &s->exit.prioq_index); - break; + if (s->enabled == m) /* No change? */ + return 0; - case SOURCE_DEFER: - case SOURCE_POST: - case SOURCE_INOTIFY: + if (m == SD_EVENT_OFF) + r = event_source_offline(s, m, s->ratelimited); + else { + if (s->enabled != SD_EVENT_OFF) { + /* Switching from "on" to "oneshot" or back? If that's the case, we can take a shortcut, the + * event source is already enabled after all. */ s->enabled = m; - break; - - default: - assert_not_reached("Wut? I shouldn't exist."); + return 0; } - } - - if (s->pending) - prioq_reshuffle(s->event->pending, s, &s->pending_index); - if (s->prepare) - prioq_reshuffle(s->event->prepare, s, &s->prepare_index); + r = event_source_online(s, m, s->ratelimited); + } + if (r < 0) + return r; + event_source_pp_prioq_reshuffle(s); return 0; } @@ -2407,7 +2578,6 @@ _public_ int sd_event_source_get_time(sd_event_source *s, uint64_t *usec) { } _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { - struct clock_data *d; int r; assert_return(s, -EINVAL); @@ -2421,13 +2591,7 @@ _public_ int sd_event_source_set_time(sd_event_source *s, uint64_t usec) { s->time.next = usec; - d = event_get_clock_data(s->event, s->type); - assert(d); - - prioq_reshuffle(d->earliest, s, &s->time.earliest_index); - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; - + event_source_time_prioq_reshuffle(s); return 0; } @@ -2459,7 +2623,6 @@ _public_ int sd_event_source_get_time_accuracy(sd_event_source *s, uint64_t *use } _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec) { - struct clock_data *d; int r; assert_return(s, -EINVAL); @@ -2477,12 +2640,7 @@ _public_ int sd_event_source_set_time_accuracy(sd_event_source *s, uint64_t usec s->time.accuracy = usec; - d = event_get_clock_data(s->event, s->type); - assert(d); - - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; - + event_source_time_prioq_reshuffle(s); return 0; } @@ -2657,6 +2815,96 @@ _public_ void *sd_event_source_set_userdata(sd_event_source *s, void *userdata) return ret; } +static int event_source_enter_ratelimited(sd_event_source *s) { + int r; + + assert(s); + + /* When an event source becomes ratelimited, we place it in the CLOCK_MONOTONIC priority queue, with + * the end of the rate limit time window, much as if it was a timer event source. */ + + if (s->ratelimited) + return 0; /* Already ratelimited, this is a NOP hence */ + + /* Make sure we can install a CLOCK_MONOTONIC event further down. */ + r = setup_clock_data(s->event, &s->event->monotonic, CLOCK_MONOTONIC); + if (r < 0) + return r; + + /* Timer event sources are already using the earliest/latest queues for the timer scheduling. Let's + * first remove them from the prioq appropriate for their own clock, so that we can use the prioq + * fields of the event source then for adding it to the CLOCK_MONOTONIC prioq instead. */ + if (EVENT_SOURCE_IS_TIME(s->type)) + event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); + + /* Now, let's add the event source to the monotonic clock instead */ + r = event_source_time_prioq_put(s, &s->event->monotonic); + if (r < 0) + goto fail; + + /* And let's take the event source officially offline */ + r = event_source_offline(s, s->enabled, /* ratelimited= */ true); + if (r < 0) { + event_source_time_prioq_remove(s, &s->event->monotonic); + goto fail; + } + + event_source_pp_prioq_reshuffle(s); + + log_debug("Event source %p (%s) entered rate limit state.", s, strna(s->description)); + return 0; + +fail: + /* Reinstall time event sources in the priority queue as before. This shouldn't fail, since the queue + * space for it should already be allocated. */ + if (EVENT_SOURCE_IS_TIME(s->type)) + assert_se(event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)) >= 0); + + return r; +} + +static int event_source_leave_ratelimit(sd_event_source *s) { + int r; + + assert(s); + + if (!s->ratelimited) + return 0; + + /* Let's take the event source out of the monotonic prioq first. */ + event_source_time_prioq_remove(s, &s->event->monotonic); + + /* Let's then add the event source to its native clock prioq again — if this is a timer event source */ + if (EVENT_SOURCE_IS_TIME(s->type)) { + r = event_source_time_prioq_put(s, event_get_clock_data(s->event, s->type)); + if (r < 0) + goto fail; + } + + /* Let's try to take it online again. */ + r = event_source_online(s, s->enabled, /* ratelimited= */ false); + if (r < 0) { + /* Do something roughly sensible when this failed: undo the two prioq ops above */ + if (EVENT_SOURCE_IS_TIME(s->type)) + event_source_time_prioq_remove(s, event_get_clock_data(s->event, s->type)); + + goto fail; + } + + event_source_pp_prioq_reshuffle(s); + ratelimit_reset(&s->rate_limit); + + log_debug("Event source %p (%s) left rate limit state.", s, strna(s->description)); + return 0; + +fail: + /* Do something somewhat reasonable when we cannot move an event sources out of ratelimited mode: + * simply put it back in it, maybe we can then process it more successfully next iteration. */ + assert_se(event_source_time_prioq_put(s, &s->event->monotonic) >= 0); + + return r; +} + static usec_t sleep_between(sd_event *e, usec_t a, usec_t b) { usec_t c; assert(e); @@ -2744,7 +2992,6 @@ static int event_arm_timer( struct itimerspec its = {}; sd_event_source *a, *b; usec_t t; - int r; assert(e); assert(d); @@ -2755,7 +3002,7 @@ static int event_arm_timer( d->needs_rearm = false; a = prioq_peek(d->earliest); - if (!a || a->enabled == SD_EVENT_OFF || a->time.next == USEC_INFINITY) { + if (!a || a->enabled == SD_EVENT_OFF || time_event_source_next(a) == USEC_INFINITY) { if (d->fd < 0) return 0; @@ -2764,9 +3011,8 @@ static int event_arm_timer( return 0; /* disarm */ - r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); - if (r < 0) - return r; + if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) + return -errno; d->next = USEC_INFINITY; return 0; @@ -2775,7 +3021,7 @@ static int event_arm_timer( b = prioq_peek(d->latest); assert_se(b && b->enabled != SD_EVENT_OFF); - t = sleep_between(e, a->time.next, time_event_source_latest(b)); + t = sleep_between(e, time_event_source_next(a), time_event_source_latest(b)); if (d->next == t) return 0; @@ -2788,8 +3034,7 @@ static int event_arm_timer( } else timespec_store(&its.it_value, t); - r = timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL); - if (r < 0) + if (timerfd_settime(d->fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) return -errno; d->next = t; @@ -2854,19 +3099,29 @@ static int process_timer( for (;;) { s = prioq_peek(d->earliest); - if (!s || - s->time.next > n || - s->enabled == SD_EVENT_OFF || - s->pending) + if (!s || time_event_source_next(s) > n) + break; + + if (s->ratelimited) { + /* This is an event sources whose ratelimit window has ended. Let's turn it on + * again. */ + assert(s->ratelimited); + + r = event_source_leave_ratelimit(s); + if (r < 0) + return r; + + continue; + } + + if (s->enabled == SD_EVENT_OFF || s->pending) break; r = source_set_pending(s, true); if (r < 0) return r; - prioq_reshuffle(d->earliest, s, &s->time.earliest_index); - prioq_reshuffle(d->latest, s, &s->time.latest_index); - d->needs_rearm = true; + event_source_time_prioq_reshuffle(s); } return 0; @@ -2904,7 +3159,7 @@ static int process_child(sd_event *e) { if (s->pending) continue; - if (s->enabled == SD_EVENT_OFF) + if (event_source_is_offline(s)) continue; if (s->child.exited) @@ -2914,9 +3169,8 @@ static int process_child(sd_event *e) { continue; zero(s->child.siginfo); - r = waitid(P_PID, s->child.pid, &s->child.siginfo, - WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options); - if (r < 0) + if (waitid(P_PID, s->child.pid, &s->child.siginfo, + WNOHANG | (s->child.options & WEXITED ? WNOWAIT : 0) | s->child.options) < 0) return -errno; if (s->child.siginfo.si_pid != 0) { @@ -2952,7 +3206,7 @@ static int process_pidfd(sd_event *e, sd_event_source *s, uint32_t revents) { if (s->pending) return 0; - if (s->enabled == SD_EVENT_OFF) + if (event_source_is_offline(s)) return 0; if (!EVENT_SOURCE_WATCH_PIDFD(s)) @@ -3112,7 +3366,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { - if (s->enabled == SD_EVENT_OFF) + if (event_source_is_offline(s)) continue; r = source_set_pending(s, true); @@ -3148,7 +3402,7 @@ static int event_inotify_data_process(sd_event *e, struct inotify_data *d) { * sources if IN_IGNORED or IN_UNMOUNT is set. */ LIST_FOREACH(inotify.by_inode_data, s, inode_data->event_sources) { - if (s->enabled == SD_EVENT_OFF) + if (event_source_is_offline(s)) continue; if ((d->buffer.ev.mask & (IN_IGNORED|IN_UNMOUNT)) == 0 && @@ -3187,16 +3441,31 @@ static int process_inotify(sd_event *e) { } static int source_dispatch(sd_event_source *s) { + _cleanup_(sd_event_unrefp) sd_event *saved_event = NULL; EventSourceType saved_type; int r = 0; assert(s); assert(s->pending || s->type == SOURCE_EXIT); - /* Save the event source type, here, so that we still know it after the event callback which might invalidate - * the event. */ + /* Save the event source type, here, so that we still know it after the event callback which might + * invalidate the event. */ saved_type = s->type; + /* Similar, store a reference to the event loop object, so that we can still access it after the + * callback might have invalidated/disconnected the event source. */ + saved_event = sd_event_ref(s->event); + + /* Check if we hit the ratelimit for this event source, if so, let's disable it. */ + assert(!s->ratelimited); + if (!ratelimit_below(&s->rate_limit)) { + r = event_source_enter_ratelimited(s); + if (r < 0) + return r; + + return 1; + } + if (!IN_SET(s->type, SOURCE_DEFER, SOURCE_EXIT)) { r = source_set_pending(s, false); if (r < 0) @@ -3210,7 +3479,7 @@ static int source_dispatch(sd_event_source *s) { * post sources as pending */ SET_FOREACH(z, s->event->post_sources) { - if (z->enabled == SD_EVENT_OFF) + if (event_source_is_offline(z)) continue; r = source_set_pending(z, true); @@ -3303,9 +3572,15 @@ static int source_dispatch(sd_event_source *s) { s->dispatching = false; - if (r < 0) - log_debug_errno(r, "Event source %s (type %s) returned error, disabling: %m", - strna(s->description), event_source_type_to_string(saved_type)); + if (r < 0) { + log_debug_errno(r, "Event source %s (type %s) returned error, %s: %m", + strna(s->description), + event_source_type_to_string(saved_type), + s->exit_on_failure ? "exiting" : "disabling"); + + if (s->exit_on_failure) + (void) sd_event_exit(saved_event, r); + } if (s->n_ref == 0) source_free(s); @@ -3324,7 +3599,7 @@ static int event_prepare(sd_event *e) { sd_event_source *s; s = prioq_peek(e->prepare); - if (!s || s->prepare_iteration == e->iteration || s->enabled == SD_EVENT_OFF) + if (!s || s->prepare_iteration == e->iteration || event_source_is_offline(s)) break; s->prepare_iteration = e->iteration; @@ -3338,9 +3613,15 @@ static int event_prepare(sd_event *e) { r = s->prepare(s, s->userdata); s->dispatching = false; - if (r < 0) - log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, disabling: %m", - strna(s->description), event_source_type_to_string(s->type)); + if (r < 0) { + log_debug_errno(r, "Prepare callback of event source %s (type %s) returned error, %s: %m", + strna(s->description), + event_source_type_to_string(s->type), + s->exit_on_failure ? "exiting" : "disabling"); + + if (s->exit_on_failure) + (void) sd_event_exit(e, r); + } if (s->n_ref == 0) source_free(s); @@ -3353,18 +3634,17 @@ static int event_prepare(sd_event *e) { static int dispatch_exit(sd_event *e) { sd_event_source *p; - _cleanup_(sd_event_unrefp) sd_event *ref = NULL; int r; assert(e); p = prioq_peek(e->exit); - if (!p || p->enabled == SD_EVENT_OFF) { + if (!p || event_source_is_offline(p)) { e->state = SD_EVENT_FINISHED; return 0; } - ref = sd_event_ref(e); + _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); e->iteration++; e->state = SD_EVENT_EXITING; r = source_dispatch(p); @@ -3381,7 +3661,7 @@ static sd_event_source* event_next_pending(sd_event *e) { if (!p) return NULL; - if (p->enabled == SD_EVENT_OFF) + if (event_source_is_offline(p)) return NULL; return p; @@ -3390,7 +3670,6 @@ static sd_event_source* event_next_pending(sd_event *e) { static int arm_watchdog(sd_event *e) { struct itimerspec its = {}; usec_t t; - int r; assert(e); assert(e->watchdog_fd >= 0); @@ -3406,8 +3685,7 @@ static int arm_watchdog(sd_event *e) { if (its.it_value.tv_sec == 0 && its.it_value.tv_nsec == 0) its.it_value.tv_nsec = 1; - r = timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL); - if (r < 0) + if (timerfd_settime(e->watchdog_fd, TFD_TIMER_ABSTIME, &its, NULL) < 0) return -errno; return 0; @@ -3462,6 +3740,9 @@ _public_ int sd_event_prepare(sd_event *e) { * syscalls */ assert_return(!e->default_event_ptr || e->tid == gettid(), -EREMOTEIO); + /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ + _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); + if (e->exit_requested) goto pending; @@ -3667,9 +3948,8 @@ _public_ int sd_event_dispatch(sd_event *e) { p = event_next_pending(e); if (p) { - _cleanup_(sd_event_unrefp) sd_event *ref = NULL; + _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); - ref = sd_event_ref(e); e->state = SD_EVENT_RUNNING; r = source_dispatch(p); e->state = SD_EVENT_INITIAL; @@ -3703,29 +3983,32 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - if (e->profile_delays && e->last_run) { + if (e->profile_delays && e->last_run_usec != 0) { usec_t this_run; unsigned l; this_run = now(CLOCK_MONOTONIC); - l = u64log2(this_run - e->last_run); - assert(l < sizeof(e->delays)); + l = u64log2(this_run - e->last_run_usec); + assert(l < ELEMENTSOF(e->delays)); e->delays[l]++; - if (this_run - e->last_log >= 5*USEC_PER_SEC) { + if (this_run - e->last_log_usec >= 5*USEC_PER_SEC) { event_log_delays(e); - e->last_log = this_run; + e->last_log_usec = this_run; } } + /* Make sure that none of the preparation callbacks ends up freeing the event source under our feet */ + _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = sd_event_ref(e); + r = sd_event_prepare(e); if (r == 0) /* There was nothing? Then wait... */ r = sd_event_wait(e, timeout); if (e->profile_delays) - e->last_run = now(CLOCK_MONOTONIC); + e->last_run_usec = now(CLOCK_MONOTONIC); if (r > 0) { /* There's something now, then let's dispatch it */ @@ -3740,7 +4023,6 @@ _public_ int sd_event_run(sd_event *e, uint64_t timeout) { } _public_ int sd_event_loop(sd_event *e) { - _cleanup_(sd_event_unrefp) sd_event *ref = NULL; int r; assert_return(e, -EINVAL); @@ -3748,7 +4030,7 @@ _public_ int sd_event_loop(sd_event *e) { assert_return(!event_pid_changed(e), -ECHILD); assert_return(e->state == SD_EVENT_INITIAL, -EBUSY); - ref = sd_event_ref(e); + _unused_ _cleanup_(sd_event_unrefp) sd_event *ref = NULL; while (e->state != SD_EVENT_FINISHED) { r = sd_event_run(e, (uint64_t) -1); @@ -3760,7 +4042,6 @@ _public_ int sd_event_loop(sd_event *e) { } _public_ int sd_event_get_fd(sd_event *e) { - assert_return(e, -EINVAL); assert_return(e = event_resolve(e), -ENOPKG); assert_return(!event_pid_changed(e), -ECHILD); @@ -3817,8 +4098,7 @@ _public_ int sd_event_now(sd_event *e, clockid_t clock, uint64_t *usec) { return -EOPNOTSUPP; if (!triple_timestamp_is_set(&e->timestamp)) { - /* Implicitly fall back to now() if we never ran - * before and thus have no cached time. */ + /* Implicitly fall back to now() if we never ran before and thus have no cached time. */ *usec = now(clock); return 1; } @@ -3898,8 +4178,7 @@ _public_ int sd_event_set_watchdog(sd_event *e, int b) { .data.ptr = INT_TO_PTR(SOURCE_WATCHDOG), }; - r = epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev); - if (r < 0) { + if (epoll_ctl(e->epoll_fd, EPOLL_CTL_ADD, e->watchdog_fd, &ev) < 0) { r = -errno; goto fail; } @@ -3979,4 +4258,72 @@ _public_ int sd_event_source_set_floating(sd_event_source *s, int b) { return 1; } + +_public_ int sd_event_source_get_exit_on_failure(sd_event_source *s) { + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + + return s->exit_on_failure; +} + +_public_ int sd_event_source_set_exit_on_failure(sd_event_source *s, int b) { + assert_return(s, -EINVAL); + assert_return(s->type != SOURCE_EXIT, -EDOM); + + if (s->exit_on_failure == !!b) + return 0; + + s->exit_on_failure = b; + return 1; +} + +_public_ int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval, unsigned burst) { + int r; + + assert_return(s, -EINVAL); + + /* Turning on ratelimiting on event source types that don't support it, is a loggable offense. Doing + * so is a programming error. */ + assert_return(EVENT_SOURCE_CAN_RATE_LIMIT(s->type), -EDOM); + + /* When ratelimiting is configured we'll always reset the rate limit state first and start fresh, + * non-ratelimited. */ + r = event_source_leave_ratelimit(s); + if (r < 0) + return r; + + s->rate_limit = (RateLimit) { interval, burst }; + return 0; +} + +_public_ int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval, unsigned *ret_burst) { + assert_return(s, -EINVAL); + + /* Querying whether an event source has ratelimiting configured is not a loggable offsense, hence + * don't use assert_return(). Unlike turning on ratelimiting it's not really a programming error */ + if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) + return -EDOM; + + if (!ratelimit_configured(&s->rate_limit)) + return -ENOEXEC; + + if (ret_interval) + *ret_interval = s->rate_limit.interval; + if (ret_burst) + *ret_burst = s->rate_limit.burst; + + return 0; +} + +_public_ int sd_event_source_is_ratelimited(sd_event_source *s) { + assert_return(s, -EINVAL); + + if (!EVENT_SOURCE_CAN_RATE_LIMIT(s->type)) + return false; + + if (!ratelimit_configured(&s->rate_limit)) + return false; + + return s->ratelimited; +} #endif /* NM_IGNORED */ diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.c b/src/core/systemd/src/libsystemd/sd-id128/id128-util.c index 3cb96378..b61cfdb0 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.c +++ b/src/core/systemd/src/libsystemd/sd-id128/id128-util.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" @@ -12,6 +12,7 @@ #include "id128-util.h" #include "io-util.h" #include "stdio-util.h" +#include "string-util.h" #if 0 /* NM_IGNORED */ char *id128_to_uuid_string(sd_id128_t id, char s[static ID128_UUID_STRING_MAX]) { @@ -101,6 +102,11 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { switch (l) { + case 13: + case 14: + /* Treat an "uninitialized" id file like an empty one */ + return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL; + case 33: /* plain UUID with trailing newline */ if (buffer[32] != '\n') return -EINVAL; @@ -119,7 +125,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) { _fallthrough_; case 36: /* RFC UUID without trailing newline */ - if (f == ID128_PLAIN) + if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT)) return -EINVAL; buffer[36] = 0; diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/core/systemd/src/libsystemd/sd-id128/id128-util.h index 1901bf11..6b09bcd9 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.h +++ b/src/core/systemd/src/libsystemd/sd-id128/id128-util.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include <stdbool.h> @@ -17,6 +17,10 @@ bool id128_is_valid(const char *s) _pure_; typedef enum Id128Format { ID128_ANY, ID128_PLAIN, /* formatted as 32 hex chars as-is */ + ID128_PLAIN_OR_UNINIT, /* formatted as 32 hex chars as-is; allow special "uninitialized" + * value when reading from file (id128_read() and id128_read_fd()). + * + * This format should be used when reading a machine-id file. */ ID128_UUID, /* formatted as 36 character uuid string */ _ID128_FORMAT_MAX, } Id128Format; diff --git a/src/systemd/src/libsystemd/sd-id128/sd-id128.c b/src/core/systemd/src/libsystemd/sd-id128/sd-id128.c index d585ff25..64b8c787 100644 --- a/src/systemd/src/libsystemd/sd-id128/sd-id128.c +++ b/src/core/systemd/src/libsystemd/sd-id128/sd-id128.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include "nm-sd-adapt-core.h" diff --git a/src/systemd/src/systemd/_sd-common.h b/src/core/systemd/src/systemd/_sd-common.h index 1055b00d..e3de2ae5 100644 --- a/src/systemd/src/systemd/_sd-common.h +++ b/src/core/systemd/src/systemd/_sd-common.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdcommonhfoo #define foosdcommonhfoo diff --git a/src/systemd/src/systemd/sd-dhcp-client.h b/src/core/systemd/src/systemd/sd-dhcp-client.h index ac3b5b36..c35328a9 100644 --- a/src/systemd/src/systemd/sd-dhcp-client.h +++ b/src/core/systemd/src/systemd/sd-dhcp-client.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcpclienthfoo #define foosddhcpclienthfoo @@ -40,6 +40,8 @@ enum { SD_DHCP_CLIENT_EVENT_EXPIRED = 3, SD_DHCP_CLIENT_EVENT_RENEW = 4, SD_DHCP_CLIENT_EVENT_SELECTING = 5, + SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE = 6, /* Sent when we have not received a reply after the first few attempts. + * The client may want to start acquiring link-local addresses. */ }; enum { @@ -126,6 +128,7 @@ int sd_dhcp_client_set_ifindex( int sd_dhcp_client_set_mac( sd_dhcp_client *client, const uint8_t *addr, + const uint8_t *bcast_addr, size_t addr_len, uint16_t arp_type); int sd_dhcp_client_set_client_id( diff --git a/src/systemd/src/systemd/sd-dhcp-lease.h b/src/core/systemd/src/systemd/sd-dhcp-lease.h index 17bd4918..c255a1f9 100644 --- a/src/systemd/src/systemd/sd-dhcp-lease.h +++ b/src/core/systemd/src/systemd/sd-dhcp-lease.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcpleasehfoo #define foosddhcpleasehfoo diff --git a/src/systemd/src/systemd/sd-dhcp-option.h b/src/core/systemd/src/systemd/sd-dhcp-option.h index 45dbd279..71aa479b 100644 --- a/src/systemd/src/systemd/sd-dhcp-option.h +++ b/src/core/systemd/src/systemd/sd-dhcp-option.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcpoptionhfoo #define foosddhcpoptionhfoo diff --git a/src/systemd/src/systemd/sd-dhcp6-client.h b/src/core/systemd/src/systemd/sd-dhcp6-client.h index 2b0d63a5..75ee27d6 100644 --- a/src/systemd/src/systemd/sd-dhcp6-client.h +++ b/src/core/systemd/src/systemd/sd-dhcp6-client.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcp6clienthfoo #define foosddhcp6clienthfoo diff --git a/src/systemd/src/systemd/sd-dhcp6-lease.h b/src/core/systemd/src/systemd/sd-dhcp6-lease.h index 240df74a..f77b31ac 100644 --- a/src/systemd/src/systemd/sd-dhcp6-lease.h +++ b/src/core/systemd/src/systemd/sd-dhcp6-lease.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcp6leasehfoo #define foosddhcp6leasehfoo diff --git a/src/systemd/src/systemd/sd-dhcp6-option.h b/src/core/systemd/src/systemd/sd-dhcp6-option.h index 88a49863..ddb2c7ce 100644 --- a/src/systemd/src/systemd/sd-dhcp6-option.h +++ b/src/core/systemd/src/systemd/sd-dhcp6-option.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosddhcp6optionhfoo #define foosddhcp6optionhfoo diff --git a/src/systemd/src/systemd/sd-event.h b/src/core/systemd/src/systemd/sd-event.h index dc96bfa6..2ae2a0da 100644 --- a/src/systemd/src/systemd/sd-event.h +++ b/src/core/systemd/src/systemd/sd-event.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdeventhfoo #define foosdeventhfoo @@ -160,6 +160,11 @@ int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret); int sd_event_source_get_floating(sd_event_source *s); int sd_event_source_set_floating(sd_event_source *s, int b); +int sd_event_source_get_exit_on_failure(sd_event_source *s); +int sd_event_source_set_exit_on_failure(sd_event_source *s, int b); +int sd_event_source_set_ratelimit(sd_event_source *s, uint64_t interval_usec, unsigned burst); +int sd_event_source_get_ratelimit(sd_event_source *s, uint64_t *ret_interval_usec, unsigned *ret_burst); +int sd_event_source_is_ratelimited(sd_event_source *s); /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); diff --git a/src/systemd/src/systemd/sd-id128.h b/src/core/systemd/src/systemd/sd-id128.h index 9b00b76e..02aa318a 100644 --- a/src/systemd/src/systemd/sd-id128.h +++ b/src/core/systemd/src/systemd/sd-id128.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdid128hfoo #define foosdid128hfoo diff --git a/src/systemd/src/systemd/sd-ipv4acd.h b/src/core/systemd/src/systemd/sd-ipv4acd.h index ebf723fc..2809d874 100644 --- a/src/systemd/src/systemd/sd-ipv4acd.h +++ b/src/core/systemd/src/systemd/sd-ipv4acd.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdipv4acdfoo #define foosdipv4acdfoo @@ -43,6 +43,8 @@ int sd_ipv4acd_get_address(sd_ipv4acd *acd, struct in_addr *address); int sd_ipv4acd_set_callback(sd_ipv4acd *acd, sd_ipv4acd_callback_t cb, void *userdata); int sd_ipv4acd_set_mac(sd_ipv4acd *acd, const struct ether_addr *addr); int sd_ipv4acd_set_ifindex(sd_ipv4acd *acd, int interface_index); +int sd_ipv4acd_get_ifindex(sd_ipv4acd *acd); +const char *sd_ipv4acd_get_ifname(sd_ipv4acd *acd); int sd_ipv4acd_set_address(sd_ipv4acd *acd, const struct in_addr *address); int sd_ipv4acd_is_running(sd_ipv4acd *acd); int sd_ipv4acd_start(sd_ipv4acd *acd, bool reset_conflicts); diff --git a/src/systemd/src/systemd/sd-ipv4ll.h b/src/core/systemd/src/systemd/sd-ipv4ll.h index 71bd4cfe..aa4d174e 100644 --- a/src/systemd/src/systemd/sd-ipv4ll.h +++ b/src/core/systemd/src/systemd/sd-ipv4ll.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdipv4llfoo #define foosdipv4llfoo @@ -43,6 +43,8 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address); int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_callback_t cb, void *userdata); int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr); int sd_ipv4ll_set_ifindex(sd_ipv4ll *ll, int interface_index); +int sd_ipv4ll_get_ifindex(sd_ipv4ll *ll); +const char *sd_ipv4ll_get_ifname(sd_ipv4ll *ll); int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address); int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, uint64_t seed); int sd_ipv4ll_is_running(sd_ipv4ll *ll); diff --git a/src/systemd/src/systemd/sd-lldp.h b/src/core/systemd/src/systemd/sd-lldp.h index c2abc201..f551f6b4 100644 --- a/src/systemd/src/systemd/sd-lldp.h +++ b/src/core/systemd/src/systemd/sd-lldp.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdlldphfoo #define foosdlldphfoo diff --git a/src/systemd/src/systemd/sd-ndisc.h b/src/core/systemd/src/systemd/sd-ndisc.h index 3ddfc8cb..c0e37899 100644 --- a/src/systemd/src/systemd/sd-ndisc.h +++ b/src/core/systemd/src/systemd/sd-ndisc.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ #ifndef foosdndiscfoo #define foosdndiscfoo diff --git a/src/tests/config/NetworkManager-warn.conf b/src/core/tests/config/NetworkManager-warn.conf index 80df7c52..80df7c52 100644 --- a/src/tests/config/NetworkManager-warn.conf +++ b/src/core/tests/config/NetworkManager-warn.conf diff --git a/src/tests/config/NetworkManager.conf b/src/core/tests/config/NetworkManager.conf index a447b6d6..a447b6d6 100644 --- a/src/tests/config/NetworkManager.conf +++ b/src/core/tests/config/NetworkManager.conf diff --git a/src/tests/config/NetworkManager.state b/src/core/tests/config/NetworkManager.state index 1b9d604a..1b9d604a 100644 --- a/src/tests/config/NetworkManager.state +++ b/src/core/tests/config/NetworkManager.state diff --git a/src/tests/config/bad.conf b/src/core/tests/config/bad.conf index 20d6a67a..20d6a67a 100644 --- a/src/tests/config/bad.conf +++ b/src/core/tests/config/bad.conf diff --git a/src/tests/config/conf.d/00-overrides.conf b/src/core/tests/config/conf.d/00-overrides.conf index f26ed93b..f26ed93b 100644 --- a/src/tests/config/conf.d/00-overrides.conf +++ b/src/core/tests/config/conf.d/00-overrides.conf diff --git a/src/tests/config/conf.d/10-more.conf b/src/core/tests/config/conf.d/10-more.conf index eadb7f96..eadb7f96 100644 --- a/src/tests/config/conf.d/10-more.conf +++ b/src/core/tests/config/conf.d/10-more.conf diff --git a/src/tests/config/conf.d/20-config-enable-1.conf b/src/core/tests/config/conf.d/20-config-enable-1.conf index e6800f52..e6800f52 100644 --- a/src/tests/config/conf.d/20-config-enable-1.conf +++ b/src/core/tests/config/conf.d/20-config-enable-1.conf diff --git a/src/tests/config/conf.d/90-last.conf b/src/core/tests/config/conf.d/90-last.conf index 7d078788..7d078788 100644 --- a/src/tests/config/conf.d/90-last.conf +++ b/src/core/tests/config/conf.d/90-last.conf diff --git a/src/tests/config/global-dns-invalid.conf b/src/core/tests/config/global-dns-invalid.conf index e490f609..e490f609 100644 --- a/src/tests/config/global-dns-invalid.conf +++ b/src/core/tests/config/global-dns-invalid.conf diff --git a/src/tests/config/meson.build b/src/core/tests/config/meson.build index cfe9c615..d0d8b1cf 100644 --- a/src/tests/config/meson.build +++ b/src/core/tests/config/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later test_config_dir = meson.current_source_dir() @@ -12,7 +12,7 @@ sources = files( exe = executable( test_unit, sources, - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) diff --git a/src/tests/config/nm-test-device.c b/src/core/tests/config/nm-test-device.c index e897f68e..f724b03a 100644 --- a/src/tests/config/nm-test-device.c +++ b/src/core/tests/config/nm-test-device.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-test-device.h" diff --git a/src/tests/config/nm-test-device.h b/src/core/tests/config/nm-test-device.h index cba17151..638177a0 100644 --- a/src/tests/config/nm-test-device.h +++ b/src/core/tests/config/nm-test-device.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ diff --git a/src/tests/config/test-config.c b/src/core/tests/config/test-config.c index b2f07b26..3bb14815 100644 --- a/src/tests/config/test-config.c +++ b/src/core/tests/config/test-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <unistd.h> @@ -16,8 +16,8 @@ #include "nm-test-utils-core.h" -#define TEST_DIR NM_BUILD_SRCDIR "/src/tests/config" -#define BUILD_DIR NM_BUILD_BUILDDIR "/src/tests/config" +#define TEST_DIR NM_BUILD_SRCDIR "/src/core/tests/config" +#define BUILD_DIR NM_BUILD_BUILDDIR "/src/core/tests/config" /*****************************************************************************/ diff --git a/src/tests/meson.build b/src/core/tests/meson.build index 8ee8bd93..994563c4 100644 --- a/src/tests/meson.build +++ b/src/core/tests/meson.build @@ -1,4 +1,4 @@ -# SPDX-License-Identifier: LGPL-2.1+ +# SPDX-License-Identifier: LGPL-2.1-or-later subdir('config') @@ -17,7 +17,7 @@ foreach test_unit: test_units exe = executable( test_unit, test_unit + '.c', - dependencies: libnetwork_manager_test_dep, + dependencies: libNetworkManagerTest_dep, c_args: test_c_flags, ) @@ -29,28 +29,24 @@ foreach test_unit: test_units ) endforeach -test_unit = 'test-systemd' - -c_flags = [ - '-DNETWORKMANAGER_COMPILATION_TEST', - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', -] - -links = [ - libnm_systemd_core, - libnm_systemd_shared, -] - exe = executable( - test_unit, - test_unit + '.c', - dependencies: daemon_nm_default_dep, - c_args: c_flags, - link_with: links, + 'test-systemd', + 'test-systemd.c', + include_directories: [ + top_inc, + src_inc, + ], + dependencies: [ + libnm_systemd_core_dep, + libnm_systemd_shared_dep, + ], + c_args: [ + '-DG_LOG_DOMAIN="test"', + ], ) test( - test_unit, + 'test-systemd', test_script, args: test_args + [exe.full_path()], ) diff --git a/src/tests/test-core-with-expect.c b/src/core/tests/test-core-with-expect.c index 62b93a04..022cf8f3 100644 --- a/src/tests/test-core-with-expect.c +++ b/src/core/tests/test-core-with-expect.c @@ -1,12 +1,11 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <time.h> -#include <netinet/ether.h> #include <sys/types.h> #include <sys/wait.h> #include <fcntl.h> @@ -236,7 +235,7 @@ do_test_nm_utils_kill_child(void) char *argv1[] = { "bash", "-c", - "trap \"sleep 0.3; exit 10\" EXIT; " + "trap \"sleep 0.5; exit 10\" EXIT; " "sleep 100000; exit $? #" TEST_TOKEN, NULL, }; @@ -335,7 +334,7 @@ do_test_nm_utils_kill_child(void) * is a race here. */ NMTST_EXPECT_NM_ERROR( "kill child process 'test-s-3-2' (*): failed due to unexpected return value -1 by waitpid " - "(No child processes, 10) after sending no signal (0)"); + "(No child process*, 10) after sending no signal (0)"); test_nm_utils_kill_child_sync_do("test-s-3-2", pid3s, 0, 0, FALSE, NULL); NMTST_EXPECT_NM_DEBUG("kill child process 'test-s-4' (*): waiting up to 1 milliseconds for " @@ -398,7 +397,7 @@ do_test_nm_utils_kill_child(void) * is a race here. */ NMTST_EXPECT_NM_ERROR( "kill child process 'test-a-3-2' (*): failed due to unexpected return value -1 by waitpid " - "(No child processes, 10) after sending no signal (0)"); + "(No child process*, 10) after sending no signal (0)"); NMTST_EXPECT_NM_DEBUG( "kill child process 'test-a-3-2' (*): invoke callback: killing child failed"); test_nm_utils_kill_child_async_do("test-a-3-2", pid3a, 0, 0, FALSE, NULL); @@ -562,30 +561,26 @@ test_nm_utils_array_remove_at_indexes(void) static void test_nm_ethernet_address_is_valid(void) { - g_assert(!nm_ethernet_address_is_valid(NULL, -1)); - g_assert(!nm_ethernet_address_is_valid(NULL, ETH_ALEN)); + g_assert(!nm_ether_addr_is_valid_str(NULL)); + g_assert(!nm_ether_addr_is_valid(NULL)); - g_assert(!nm_ethernet_address_is_valid("FF:FF:FF:FF:FF:FF", -1)); - g_assert(!nm_ethernet_address_is_valid("00:00:00:00:00:00", -1)); - g_assert(!nm_ethernet_address_is_valid("44:44:44:44:44:44", -1)); - g_assert(!nm_ethernet_address_is_valid("00:30:b4:00:00:00", -1)); + g_assert(!nm_ether_addr_is_valid_str("FF:FF:FF:FF:FF:FF")); + g_assert(!nm_ether_addr_is_valid_str("00:00:00:00:00:00")); + g_assert(!nm_ether_addr_is_valid_str("44:44:44:44:44:44")); + g_assert(!nm_ether_addr_is_valid_str("00:30:b4:00:00:00")); - g_assert(!nm_ethernet_address_is_valid("", -1)); - g_assert(!nm_ethernet_address_is_valid("1", -1)); - g_assert(!nm_ethernet_address_is_valid("2", -1)); + g_assert(!nm_ether_addr_is_valid_str("")); + g_assert(!nm_ether_addr_is_valid_str("1")); + g_assert(!nm_ether_addr_is_valid_str("2")); - g_assert( - !nm_ethernet_address_is_valid(((guint8[8]){0x00, 0x30, 0xb4, 0x00, 0x00, 0x00}), ETH_ALEN)); - g_assert( - nm_ethernet_address_is_valid(((guint8[8]){0x00, 0x30, 0xb4, 0x00, 0x00, 0x01}), ETH_ALEN)); + g_assert(!nm_ether_addr_is_valid(&NM_ETHER_ADDR_INIT(0x00, 0x30, 0xb4, 0x00, 0x00, 0x00))); + g_assert(nm_ether_addr_is_valid(&NM_ETHER_ADDR_INIT(0x00, 0x30, 0xb4, 0x00, 0x00, 0x01))); /* some Broad cast addresses (with MSB of first octet set). */ - g_assert(!nm_ethernet_address_is_valid("57:44:44:44:44:44", -1)); - g_assert(nm_ethernet_address_is_valid("56:44:44:44:44:44", -1)); - g_assert( - !nm_ethernet_address_is_valid(((guint8[8]){0x03, 0x30, 0xb4, 0x00, 0x00, 0x00}), ETH_ALEN)); - g_assert( - nm_ethernet_address_is_valid(((guint8[8]){0x02, 0x30, 0xb4, 0x00, 0x00, 0x01}), ETH_ALEN)); + g_assert(!nm_ether_addr_is_valid_str("57:44:44:44:44:44")); + g_assert(nm_ether_addr_is_valid_str("56:44:44:44:44:44")); + g_assert(!nm_ether_addr_is_valid(&NM_ETHER_ADDR_INIT(0x03, 0x30, 0xb4, 0x00, 0x00, 0x00))); + g_assert(nm_ether_addr_is_valid(&NM_ETHER_ADDR_INIT(0x02, 0x30, 0xb4, 0x00, 0x00, 0x01))); } /*****************************************************************************/ diff --git a/src/tests/test-core.c b/src/core/tests/test-core.c index 37b4a625..8698c406 100644 --- a/src/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <net/if.h> #include <byteswap.h> @@ -105,6 +105,32 @@ test_logging_domains(void) /*****************************************************************************/ static void +test_logging_error(void) +{ + gs_free_error GError *error = NULL; + gboolean success; + + g_assert_cmpint(NM_MANAGER_ERROR, ==, _NM_MANAGER_ERROR); + G_STATIC_ASSERT_EXPR(NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL == _NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL); + G_STATIC_ASSERT_EXPR(NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN + == _NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN); + + success = nm_logging_setup("bogus", "ALL", NULL, &error); + nmtst_assert_no_success(success, error); + g_assert_cmpint(error->domain, ==, NM_MANAGER_ERROR); + g_assert_cmpint(error->code, ==, NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL); + nm_clear_pointer(&error, g_error_free); + + success = nm_logging_setup("debug", "bogus", NULL, &error); + nmtst_assert_no_success(success, error); + g_assert_cmpint(error->domain, ==, NM_MANAGER_ERROR); + g_assert_cmpint(error->code, ==, NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN); + nm_clear_pointer(&error, g_error_free); +} + +/*****************************************************************************/ + +static void _test_same_prefix(const char *a1, const char *a2, guint8 plen) { struct in6_addr a = *nmtst_inet6_from_string(a1); @@ -980,10 +1006,11 @@ test_connection_match_ip6_routes(void) g_assert(matched == copy); } -#define do_test_wildcard_match(str, result, ...) \ - g_assert( \ - nm_wildcard_match_check(str, (const char *const[]){__VA_ARGS__}, NM_NARG(__VA_ARGS__)) \ - == result); +#define do_test_wildcard_match_eval(str, ...) \ + nm_wildcard_match_check(str, (const char *const[]){__VA_ARGS__}, NM_NARG(__VA_ARGS__)) + +#define do_test_wildcard_match(str, result, ...) \ + g_assert(do_test_wildcard_match_eval(str, __VA_ARGS__) == result) static void test_wildcard_match(void) @@ -1056,7 +1083,14 @@ test_wildcard_match(void) do_test_wildcard_match("name3", TRUE, "name[123]"); do_test_wildcard_match("name4", FALSE, "name[123]"); - do_test_wildcard_match("[a]", TRUE, "\\[a\\]"); + if (do_test_wildcard_match_eval("[a]", "\\[a\\]") != TRUE) { +#if defined(__GLIBC__) + do_test_wildcard_match("[a]", TRUE, "\\[a\\]"); + g_assert_not_reached(); +#endif + /* It seems musl's fnmatch() does not like such ranges. */ + g_test_skip("libc does not support ranges with fnmatch()!!"); + } do_test_wildcard_match("aa", FALSE, "!a*"); do_test_wildcard_match("aa", FALSE, "&!a*"); @@ -1929,7 +1963,7 @@ test_reverse_dns_ip4(void) GPtrArray *domains = g_ptr_array_new_full(8, g_free); inet_pton(AF_INET, "7.2.3.0", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 27, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 27, domains); g_assert_cmpuint(domains->len, ==, 32); g_assert_cmpstr(domains->pdata[0], ==, "0.3.2.7.in-addr.arpa"); g_assert_cmpstr(domains->pdata[31], ==, "31.3.2.7.in-addr.arpa"); @@ -1937,7 +1971,7 @@ test_reverse_dns_ip4(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "10.155.16.0", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 22, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 22, domains); g_assert_cmpuint(domains->len, ==, 4); g_assert_cmpstr(domains->pdata[0], ==, "16.155.10.in-addr.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "17.155.10.in-addr.arpa"); @@ -1947,21 +1981,21 @@ test_reverse_dns_ip4(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "4.5.6.7", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 32, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 32, domains); g_assert_cmpuint(domains->len, ==, 1); g_assert_cmpstr(domains->pdata[0], ==, "7.6.5.4.in-addr.arpa"); g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "4.5.6.7", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 8, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 8, domains); g_assert_cmpuint(domains->len, ==, 1); g_assert_cmpstr(domains->pdata[0], ==, "4.in-addr.arpa"); g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "4.180.6.7", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 9, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 9, domains); g_assert_cmpuint(domains->len, ==, 128); g_assert_cmpstr(domains->pdata[0], ==, "128.4.in-addr.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "129.4.in-addr.arpa"); @@ -1970,7 +2004,7 @@ test_reverse_dns_ip4(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "172.16.0.0", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 12, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 12, domains); g_assert_cmpuint(domains->len, ==, 16); g_assert_cmpstr(domains->pdata[0], ==, "16.172.in-addr.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "17.172.in-addr.arpa"); @@ -1980,7 +2014,7 @@ test_reverse_dns_ip4(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET, "1.2.3.4", &addr); - nm_utils_get_reverse_dns_domains_ip4(addr, 0, domains); + nm_utils_get_reverse_dns_domains_ip_4(addr, 0, domains); g_assert_cmpuint(domains->len, ==, 0); g_ptr_array_unref(domains); @@ -1993,14 +2027,14 @@ test_reverse_dns_ip6(void) GPtrArray * domains = g_ptr_array_new_full(8, g_free); inet_pton(AF_INET6, "1234::56", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 16, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 16, domains); g_assert_cmpuint(domains->len, ==, 1); g_assert_cmpstr(domains->pdata[0], ==, "4.3.2.1.ip6.arpa"); g_ptr_array_set_size(domains, 0); inet_pton(AF_INET6, "1234::56", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 17, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 17, domains); g_assert_cmpuint(domains->len, ==, 8); g_assert_cmpstr(domains->pdata[0], ==, "0.4.3.2.1.ip6.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "1.4.3.2.1.ip6.arpa"); @@ -2009,7 +2043,7 @@ test_reverse_dns_ip6(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET6, "2001:db8::", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 29, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 29, domains); g_assert_cmpuint(domains->len, ==, 8); g_assert_cmpstr(domains->pdata[0], ==, "8.b.d.0.1.0.0.2.ip6.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "9.b.d.0.1.0.0.2.ip6.arpa"); @@ -2018,7 +2052,7 @@ test_reverse_dns_ip6(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET6, "0123:4567:89ab:cdef::", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 63, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 63, domains); g_assert_cmpuint(domains->len, ==, 2); g_assert_cmpstr(domains->pdata[0], ==, "e.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); g_assert_cmpstr(domains->pdata[1], ==, "f.e.d.c.b.a.9.8.7.6.5.4.3.2.1.0.ip6.arpa"); @@ -2026,7 +2060,7 @@ test_reverse_dns_ip6(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET6, "fec0:1234:5678:9ab0::", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 61, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 61, domains); g_assert_cmpuint(domains->len, ==, 8); g_assert_cmpstr(domains->pdata[0], ==, "0.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); g_assert_cmpstr(domains->pdata[7], ==, "7.b.a.9.8.7.6.5.4.3.2.1.0.c.e.f.ip6.arpa"); @@ -2034,7 +2068,7 @@ test_reverse_dns_ip6(void) g_ptr_array_set_size(domains, 0); inet_pton(AF_INET6, "0123:4567:89ab:cdee::", &addr); - nm_utils_get_reverse_dns_domains_ip6(&addr, 0, domains); + nm_utils_get_reverse_dns_domains_ip_6(&addr, 0, domains); g_assert_cmpuint(domains->len, ==, 0); g_ptr_array_unref(domains); @@ -2536,6 +2570,7 @@ main(int argc, char **argv) nmtst_init_with_logging(&argc, &argv, NULL, "ALL"); g_test_add_func("/general/test_logging_domains", test_logging_domains); + g_test_add_func("/general/test_logging_error", test_logging_error); g_test_add_func("/general/nm_utils_strbuf_append", test_nm_utils_strbuf_append); diff --git a/src/tests/test-dcb.c b/src/core/tests/test-dcb.c index 0df21066..fc591fcb 100644 --- a/src/tests/test-dcb.c +++ b/src/core/tests/test-dcb.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-dcb.h" diff --git a/src/tests/test-ip4-config.c b/src/core/tests/test-ip4-config.c index 5a9eae90..27b1d611 100644 --- a/src/tests/test-ip4-config.c +++ b/src/core/tests/test-ip4-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 - 2014 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <arpa/inet.h> diff --git a/src/tests/test-ip6-config.c b/src/core/tests/test-ip6-config.c index 6b995fe5..3b48fb7f 100644 --- a/src/tests/test-ip6-config.c +++ b/src/core/tests/test-ip6-config.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2013 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <arpa/inet.h> #include <linux/if_addr.h> diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c new file mode 100644 index 00000000..43132c6d --- /dev/null +++ b/src/core/tests/test-l3cfg.c @@ -0,0 +1,795 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include "src/core/nm-default-daemon.h" + +#include "nm-l3cfg.h" +#include "nm-l3-ipv4ll.h" +#include "nm-netns.h" +#include "platform/nm-platform.h" + +#include "platform/tests/test-common.h" + +/*****************************************************************************/ + +static NML3Cfg * +_netns_access_l3cfg(NMNetns *netns, int ifindex) +{ + NML3Cfg *l3cfg; + + g_assert(NM_IS_NETNS(netns)); + g_assert(ifindex > 0); + + g_assert(!nm_netns_get_l3cfg(netns, ifindex)); + + l3cfg = nm_netns_access_l3cfg(netns, ifindex); + g_assert(NM_IS_L3CFG(l3cfg)); + return l3cfg; +} + +/*****************************************************************************/ + +typedef struct { + int test_idx; + NMPlatform * platform; + NMNetns * netns; + NMDedupMultiIndex *multiidx; + const char * ifname0; + const char * ifname1; + NMPLinkAddress hwaddr0; + NMPLinkAddress hwaddr1; + int ifindex0; + int ifindex1; +} TestFixture1; + +static const TestFixture1 * +_test_fixture_1_setup(TestFixture1 *f, int test_idx) +{ + const NMPlatformLink *l0; + const NMPlatformLink *l1; + const NMEtherAddr addr0 = NM_ETHER_ADDR_INIT(0xAA, 0xAA, test_idx, 0x00, 0x00, 0x00); + const NMEtherAddr addr1 = NM_ETHER_ADDR_INIT(0xAA, 0xAA, test_idx, 0x00, 0x00, 0x11); + + g_assert_cmpint(test_idx, >, 0); + g_assert_cmpint(f->test_idx, ==, 0); + + f->test_idx = test_idx; + + f->ifname0 = "nm-test-veth0"; + f->ifname1 = "nm-test-veth1"; + + f->platform = g_object_ref(NM_PLATFORM_GET); + f->multiidx = nm_dedup_multi_index_ref(nm_platform_get_multi_idx(f->platform)); + f->netns = nm_netns_new(f->platform); + + nmtstp_link_veth_add(f->platform, -1, f->ifname0, f->ifname1); + + l0 = nmtstp_link_get_typed(f->platform, -1, f->ifname0, NM_LINK_TYPE_VETH); + l1 = nmtstp_link_get_typed(f->platform, -1, f->ifname1, NM_LINK_TYPE_VETH); + + f->ifindex0 = l0->ifindex; + f->ifindex1 = l1->ifindex; + + g_assert_cmpint(nm_platform_link_set_address(f->platform, f->ifindex0, &addr0, sizeof(addr0)), + ==, + 0); + g_assert_cmpint(nm_platform_link_set_address(f->platform, f->ifindex1, &addr1, sizeof(addr1)), + ==, + 0); + + l0 = nmtstp_link_get_typed(f->platform, f->ifindex0, f->ifname0, NM_LINK_TYPE_VETH); + l1 = nmtstp_link_get_typed(f->platform, f->ifindex1, f->ifname1, NM_LINK_TYPE_VETH); + + f->hwaddr0 = l0->l_address; + f->hwaddr1 = l1->l_address; + + g_assert(nm_platform_link_set_up(f->platform, f->ifindex0, NULL)); + g_assert(nm_platform_link_set_up(f->platform, f->ifindex1, NULL)); + + return f; +} + +static void +_test_fixture_1_teardown(TestFixture1 *f) +{ + g_assert(f); + + if (f->test_idx == 0) + return; + + _LOGD("test teatdown"); + + nmtstp_link_delete(f->platform, -1, f->ifindex0, f->ifname0, TRUE); + g_assert(!nm_platform_link_get(f->platform, f->ifindex0)); + g_assert(!nm_platform_link_get(f->platform, f->ifindex1)); + g_assert(!nm_platform_link_get_by_ifname(f->platform, f->ifname0)); + g_assert(!nm_platform_link_get_by_ifname(f->platform, f->ifname1)); + + g_object_unref(f->netns); + g_object_unref(f->platform); + nm_dedup_multi_index_unref(f->multiidx); + + *f = (TestFixture1){ + .test_idx = 0, + }; +} + +/*****************************************************************************/ + +typedef enum { + TEST_L3CFG_NOTIFY_TYPE_NONE, + TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL, + TEST_L3CFG_NOTIFY_TYPE_COMMIT_1, + TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1, +} TestL3cfgNotifyType; + +typedef struct { + const TestFixture1 *f; + + bool has_addr4_101 : 1; + bool add_addr4_101 : 1; + + guint32 acd_timeout_msec_a; + NML3AcdDefendType acd_defend_type_a; + + TestL3cfgNotifyType notify_type; + guint post_commit_event_count; + guint general_event_count; + guint general_event_flags; + union { + struct { + int cb_count; + bool expected_probe_result : 1; + bool acd_event_ready_45 : 1; + bool acd_event_ready_101 : 1; + } wait_for_acd_ready_1; + } notify_result; +} TestL3cfgData; + +static void +_test_l3cfg_data_set_notify_type(TestL3cfgData *tdata, TestL3cfgNotifyType notify_type) +{ + g_assert(tdata); + + tdata->notify_type = notify_type; + tdata->post_commit_event_count = 0; + tdata->general_event_count = 0; + tdata->general_event_flags = 0; + memset(&tdata->notify_result, 0, sizeof(tdata->notify_result)); +} + +static void +_test_l3cfg_signal_notify(NML3Cfg * l3cfg, + const NML3ConfigNotifyData *notify_data, + TestL3cfgData * tdata) +{ + guint i; + + g_assert(NM_IS_L3CFG(l3cfg)); + g_assert(tdata); + g_assert(notify_data); + g_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type)); + g_assert(notify_data->notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM); + + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE) + g_assert(notify_data->platform_change_on_idle.obj_type_flags != 0u); + else if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE) { + g_assert(NMP_OBJECT_IS_VALID(notify_data->platform_change.obj)); + g_assert(notify_data->platform_change.change_type != 0); + } else if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT) { + g_assert_cmpint(notify_data->acd_event.info.n_track_infos, >=, 1); + g_assert(notify_data->acd_event.info.track_infos); + for (i = 0; i < notify_data->acd_event.info.n_track_infos; i++) { + const NML3AcdAddrTrackInfo *ti = ¬ify_data->acd_event.info.track_infos[i]; + + nm_assert(NMP_OBJECT_GET_TYPE(ti->obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); + nm_assert(NMP_OBJECT_CAST_IP4_ADDRESS(ti->obj)->address + == notify_data->acd_event.info.addr); + nm_assert(NM_IS_L3_CONFIG_DATA(ti->l3cd)); + nm_assert(ti->tag); + } + } + + switch (tdata->notify_type) { + case TEST_L3CFG_NOTIFY_TYPE_NONE: + g_assert_not_reached(); + break; + case TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL: + if (NM_IN_SET(notify_data->notify_type, + NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, + NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)) + return; + g_assert_not_reached(); + return; + case TEST_L3CFG_NOTIFY_TYPE_COMMIT_1: + g_assert_cmpint(tdata->post_commit_event_count, ==, 0); + switch (notify_data->notify_type) { + case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: + tdata->post_commit_event_count++; + return; + case NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT: + switch (tdata->f->test_idx) { + case 2: + case 3: + nmtst_assert_ip4_address(notify_data->acd_event.info.addr, "192.168.133.45"); + if (tdata->f->test_idx == 2) + g_assert(notify_data->acd_event.info.state == NM_L3_ACD_ADDR_STATE_DEFENDING); + else + g_assert(notify_data->acd_event.info.state == NM_L3_ACD_ADDR_STATE_PROBING); + g_assert(tdata->general_event_count == 0); + tdata->general_event_count++; + return; + case 4: + if (notify_data->acd_event.info.addr == nmtst_inet4_from_string("192.168.133.45")) { + g_assert(!NM_FLAGS_HAS(tdata->general_event_flags, 0x1u)); + tdata->general_event_flags |= 0x1u; + g_assert(notify_data->acd_event.info.state == NM_L3_ACD_ADDR_STATE_PROBING); + tdata->general_event_count++; + } else if (notify_data->acd_event.info.addr + == nmtst_inet4_from_string("192.168.133.101")) { + g_assert(!NM_FLAGS_HAS(tdata->general_event_flags, 0x4u)); + tdata->general_event_flags |= 0x4u; + g_assert(notify_data->acd_event.info.state == NM_L3_ACD_ADDR_STATE_PROBING); + tdata->general_event_count++; + } else + g_assert_not_reached(); + return; + default: + g_assert_not_reached(); + return; + } + case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE: + return; + default: + g_assert_not_reached(); + return; + } + case TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1: + { + int num_acd_completed_events = + 1 + 2 + (tdata->add_addr4_101 ? (tdata->has_addr4_101 ? 1 : 3) : 0); + + if (NM_IN_SET(notify_data->notify_type, + NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, + NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)) + return; + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_EVENT) { + if (notify_data->acd_event.info.addr == nmtst_inet4_from_string("192.168.133.45")) { + g_assert(NM_IN_SET(notify_data->acd_event.info.state, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING)); + tdata->notify_result.wait_for_acd_ready_1.acd_event_ready_45 = TRUE; + } else if (notify_data->acd_event.info.addr + == nmtst_inet4_from_string("192.168.133.101")) { + if (tdata->has_addr4_101) { + g_assert( + NM_IN_SET(notify_data->acd_event.info.state, NM_L3_ACD_ADDR_STATE_USED)); + } else { + g_assert(NM_IN_SET(notify_data->acd_event.info.state, + NM_L3_ACD_ADDR_STATE_READY, + NM_L3_ACD_ADDR_STATE_DEFENDING)); + tdata->notify_result.wait_for_acd_ready_1.acd_event_ready_101 = TRUE; + } + } else + g_assert_not_reached(); + + g_assert_cmpint(tdata->notify_result.wait_for_acd_ready_1.cb_count, + <, + num_acd_completed_events); + tdata->notify_result.wait_for_acd_ready_1.cb_count++; + return; + } + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT) { + g_assert_cmpint(tdata->notify_result.wait_for_acd_ready_1.cb_count, >, 0); + g_assert_cmpint(tdata->notify_result.wait_for_acd_ready_1.cb_count, + <, + num_acd_completed_events); + tdata->notify_result.wait_for_acd_ready_1.cb_count++; + nmtstp_platform_ip_addresses_assert( + tdata->f->platform, + tdata->f->ifindex0, + TRUE, + TRUE, + TRUE, + tdata->notify_result.wait_for_acd_ready_1.acd_event_ready_45 ? "192.168.133.45" + : NULL, + tdata->notify_result.wait_for_acd_ready_1.acd_event_ready_101 ? "192.168.133.101" + : NULL, + "1:2:3:4::45"); + return; + } + g_assert_not_reached(); + return; + } + } + + g_assert_not_reached(); +} + +static void +test_l3cfg(gconstpointer test_data) +{ + const int TEST_IDX = GPOINTER_TO_INT(test_data); + const guint32 ACD_TIMEOUT_BASE_MSEC = 1000; + nm_auto(_test_fixture_1_teardown) TestFixture1 test_fixture = {}; + const TestFixture1 * f; + NML3CfgCommitTypeHandle * commit_type_1; + NML3CfgCommitTypeHandle * commit_type_2; + gs_unref_object NML3Cfg *l3cfg0 = NULL; + nm_auto_unref_l3cd const NML3ConfigData *l3cd_a = NULL; + TestL3cfgData tdata_stack = { + .f = NULL, + }; + TestL3cfgData *const tdata = &tdata_stack; + + _LOGD("test start (/l3cfg/%d)", TEST_IDX); + + if (nmtst_test_quick()) { + gs_free char *msg = + g_strdup_printf("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", + g_get_prgname() ?: "test-l3cfg"); + + g_test_skip(msg); + return; + } + + f = _test_fixture_1_setup(&test_fixture, TEST_IDX); + + tdata->f = f; + tdata->has_addr4_101 = (f->test_idx == 4 && nmtst_get_rand_bool()); + tdata->add_addr4_101 = (f->test_idx == 4 && nmtst_get_rand_bool()); + + tdata->acd_timeout_msec_a = NM_IN_SET(f->test_idx, 3, 4) ? ACD_TIMEOUT_BASE_MSEC : 0u; + tdata->acd_defend_type_a = NM_IN_SET(f->test_idx, 4) + ? nmtst_rand_select(NM_L3_ACD_DEFEND_TYPE_NEVER, + NM_L3_ACD_DEFEND_TYPE_ONCE, + NM_L3_ACD_DEFEND_TYPE_ALWAYS) + : NM_L3_ACD_DEFEND_TYPE_NEVER; + + if (tdata->has_addr4_101) { + nmtstp_ip4_address_add(f->platform, + -1, + f->ifindex1, + nmtst_inet4_from_string("192.168.133.101"), + 24, + nmtst_inet4_from_string("192.168.133.101"), + 100000, + 0, + 0, + NULL); + } + + l3cfg0 = _netns_access_l3cfg(f->netns, f->ifindex0); + + g_signal_connect(l3cfg0, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_test_l3cfg_signal_notify), tdata); + + commit_type_1 = nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL); + + if (!nmtst_get_rand_one_case_in(4)) { + commit_type_2 = + nm_l3cfg_commit_type_register(l3cfg0, + nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, + NM_L3_CFG_COMMIT_TYPE_ASSUME, + NM_L3_CFG_COMMIT_TYPE_UPDATE), + NULL); + } else + commit_type_2 = NULL; + + switch (f->test_idx) { + case 1: + break; + case 2: + case 3: + case 4: + { + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + + l3cd = nm_l3_config_data_new(f->multiidx, f->ifindex0); + + nm_l3_config_data_add_address_4( + l3cd, + NM_PLATFORM_IP4_ADDRESS_INIT(.address = nmtst_inet4_from_string("192.168.133.45"), + .peer_address = nmtst_inet4_from_string("192.168.133.45"), + .plen = 24, )); + + if (tdata->add_addr4_101) { + nm_l3_config_data_add_address_4( + l3cd, + NM_PLATFORM_IP4_ADDRESS_INIT(.address = nmtst_inet4_from_string("192.168.133.101"), + .peer_address = + nmtst_inet4_from_string("192.168.133.101"), + .plen = 24, )); + } + + nm_l3_config_data_add_address_6( + l3cd, + NM_PLATFORM_IP6_ADDRESS_INIT(.address = *nmtst_inet6_from_string("1:2:3:4::45"), + .plen = 64, )); + + if (nmtst_get_rand_one_case_in(2)) + nm_l3_config_data_seal(l3cd); + l3cd_a = g_steal_pointer(&l3cd); + break; + } + } + + nm_l3_config_data_log(l3cd_a, "l3cd_a", "platform-test: l3cd_a: ", LOGL_DEBUG, LOGD_PLATFORM); + + if (l3cd_a) { + nm_l3cfg_add_config(l3cfg0, + GINT_TO_POINTER('a'), + nmtst_get_rand_bool(), + l3cd_a, + 'a', + 0, + 0, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, + NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, + 0, + 0, + tdata->acd_defend_type_a, + tdata->acd_timeout_msec_a, + NM_L3_CONFIG_MERGE_FLAGS_NONE); + } + + nm_l3_config_data_log(nm_l3cfg_get_combined_l3cd(l3cfg0, FALSE), + "test", + "platform-test: l3cfg0: ", + LOGL_DEBUG, + LOGD_PLATFORM); + + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_COMMIT_1); + nm_l3cfg_commit(l3cfg0, NM_L3_CFG_COMMIT_TYPE_REAPPLY); + g_assert_cmpint(tdata->post_commit_event_count, ==, 1); + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); + + nmtstp_platform_ip_addresses_assert(tdata->f->platform, + tdata->f->ifindex0, + TRUE, + TRUE, + TRUE, + NM_IN_SET(f->test_idx, 2) ? "192.168.133.45" : NULL, + NM_IN_SET(f->test_idx, 2, 3, 4) ? "1:2:3:4::45" : NULL); + + if (NM_IN_SET(f->test_idx, 1, 2)) { + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL); + _LOGT("poll 1 start"); + nmtst_main_context_iterate_until(NULL, + nmtst_get_rand_uint32() % (ACD_TIMEOUT_BASE_MSEC * 5u), + FALSE); + _LOGT("poll 1 end"); + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); + } + + if (NM_IN_SET(f->test_idx, 3, 4)) { + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1); + tdata->notify_result.wait_for_acd_ready_1.expected_probe_result = TRUE; + _LOGT("poll 2 start"); + nmtst_main_context_iterate_until( + NULL, + ACD_TIMEOUT_BASE_MSEC * 3u / 2u + + (nmtst_get_rand_uint32() % (2u * ACD_TIMEOUT_BASE_MSEC)), + FALSE); + _LOGT("poll 2 end"); + g_assert_cmpint(tdata->notify_result.wait_for_acd_ready_1.cb_count, + ==, + 1 + 2 + (tdata->add_addr4_101 ? (tdata->has_addr4_101 ? 1 : 3) : 0)); + _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); + } + + g_signal_handlers_disconnect_by_func(l3cfg0, G_CALLBACK(_test_l3cfg_signal_notify), tdata); + + nm_l3cfg_commit_type_unregister(l3cfg0, commit_type_1); + nm_l3cfg_commit_type_unregister(l3cfg0, commit_type_2); + + if (nmtst_get_rand_one_case_in(3)) + _test_fixture_1_teardown(&test_fixture); + + nm_l3cfg_remove_config_all(l3cfg0, GINT_TO_POINTER('a'), FALSE); + + if (nmtst_get_rand_one_case_in(3)) + _test_fixture_1_teardown(&test_fixture); + + _LOGD("test end (/l3cfg/%d)", TEST_IDX); +} + +/*****************************************************************************/ + +#define L3IPV4LL_ACD_TIMEOUT_MSEC 1500u + +typedef struct { + const TestFixture1 * f; + NML3CfgCommitTypeHandle *l3cfg_commit_type_1; + guint acd_timeout_msec; + NML3IPv4LL * l3ipv4ll; + bool has_addr4_101; + gint8 ready_seen; + gint8 addr_commit; + in_addr_t addr_commit_addr; + bool add_conflict_checked : 1; + bool add_conflict_done; +} TestL3IPv4LLData; + +static gconstpointer +TEST_L3_IPV4LL_TAG(const TestL3IPv4LLData *tdata, guint offset) +{ + return (&(((const char *) tdata)[offset])); +} + +static void +_test_l3_ipv4ll_maybe_add_addr_4(const TestL3IPv4LLData *tdata, + int ifindex, + guint one_case_in_num, + bool * has_addr, + const char * addr) +{ + if (has_addr) { + if (*has_addr || !nmtst_get_rand_one_case_in(one_case_in_num)) + return; + *has_addr = TRUE; + } + + if (ifindex == 0) + ifindex = tdata->f->ifindex0; + + g_assert_cmpint(ifindex, >, 0); + + _LOGT("add test address: %s on ifindex=%d", addr, ifindex); + + nmtstp_ip4_address_add(tdata->f->platform, + -1, + ifindex, + nmtst_inet4_from_string(addr), + 24, + nmtst_inet4_from_string(addr), + 100000, + 0, + 0, + NULL); +} + +static void +_test_l3_ipv4ll_signal_notify(NML3Cfg * l3cfg, + const NML3ConfigNotifyData *notify_data, + TestL3IPv4LLData * tdata) +{ + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + g_assert(NM_IS_L3CFG(l3cfg)); + g_assert(tdata); + g_assert(notify_data); + g_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type)); + g_assert(notify_data->notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM); + + if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_IPV4LL_EVENT) { + g_assert(tdata->l3ipv4ll == notify_data->ipv4ll_event.ipv4ll); + g_assert(NM_IN_SET(tdata->ready_seen, 0, 1)); + g_assert(NM_IN_SET(tdata->addr_commit, 0, 1)); + + if (nm_l3_ipv4ll_get_state(tdata->l3ipv4ll) == NM_L3_IPV4LL_STATE_READY) { + g_assert_cmpint(tdata->ready_seen, ==, 0); + g_assert_cmpint(tdata->addr_commit, ==, 0); + tdata->ready_seen++; + + if (tdata->f->test_idx == 2 && nmtst_get_rand_bool()) { + tdata->addr_commit++; + tdata->addr_commit_addr = nm_l3_ipv4ll_get_addr(tdata->l3ipv4ll); + g_assert(nm_utils_ip4_address_is_link_local(tdata->addr_commit_addr)); + _LOGT("add address %s that passed ACD", + _nm_utils_inet4_ntop(tdata->addr_commit_addr, sbuf_addr)); + if (!nm_l3cfg_add_config(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + TEST_L3_IPV4LL_TAG(tdata, 1), + nmtst_get_rand_bool(), + nm_l3_ipv4ll_get_l3cd(tdata->l3ipv4ll), + NM_L3CFG_CONFIG_PRIORITY_IPV4LL, + 0, + 0, + 104, + 105, + 0, + 0, + NM_L3_ACD_DEFEND_TYPE_ONCE, + nmtst_get_rand_bool() ? tdata->acd_timeout_msec : 0u, + NM_L3_CONFIG_MERGE_FLAGS_NONE)) + g_assert_not_reached(); + nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll)); + + tdata->l3cfg_commit_type_1 = + nm_l3cfg_commit_type_register(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + NM_L3_CFG_COMMIT_TYPE_UPDATE, + tdata->l3cfg_commit_type_1); + } + } else if (nm_l3_ipv4ll_get_state(tdata->l3ipv4ll) != NM_L3_IPV4LL_STATE_DEFENDING + && tdata->ready_seen > 0) { + g_assert_cmpint(tdata->ready_seen, ==, 1); + tdata->ready_seen--; + if (tdata->addr_commit > 0) { + g_assert_cmpint(tdata->addr_commit, ==, 1); + tdata->addr_commit--; + g_assert(nm_utils_ip4_address_is_link_local(tdata->addr_commit_addr)); + _LOGT("remove address %s that previously passed ACD", + _nm_utils_inet4_ntop(tdata->addr_commit_addr, sbuf_addr)); + if (!nm_l3cfg_remove_config_all(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + TEST_L3_IPV4LL_TAG(tdata, 1), + FALSE)) + g_assert_not_reached(); + nm_l3cfg_commit_on_idle_schedule(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll)); + nm_l3cfg_commit_type_unregister(nm_l3_ipv4ll_get_l3cfg(tdata->l3ipv4ll), + g_steal_pointer(&tdata->l3cfg_commit_type_1)); + } + } + return; + } +} + +static void +test_l3_ipv4ll(gconstpointer test_data) +{ + const int TEST_IDX = GPOINTER_TO_INT(test_data); + nm_auto(_test_fixture_1_teardown) TestFixture1 test_fixture = {}; + const TestFixture1 * f; + gs_unref_object NML3Cfg *l3cfg0 = NULL; + TestL3IPv4LLData tdata_stack = { + .f = NULL, + }; + TestL3IPv4LLData *const tdata = &tdata_stack; + NMTstpAcdDefender * acd_defender_1 = NULL; + NMTstpAcdDefender * acd_defender_2 = NULL; + nm_auto_unref_l3ipv4ll NML3IPv4LL * l3ipv4ll = NULL; + gint64 start_time_msec; + gint64 total_poll_time_msec; + nm_auto_remove_l3ipv4ll_registration NML3IPv4LLRegistration *l3ipv4ll_reg = NULL; + char sbuf_addr[NM_UTILS_INET_ADDRSTRLEN]; + + _LOGD("test start (/l3-ipv4ll/%d)", TEST_IDX); + + if (nmtst_test_quick()) { + gs_free char *msg = + g_strdup_printf("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", + g_get_prgname() ?: "test-l3-ipv4ll"); + + g_test_skip(msg); + return; + } + + f = _test_fixture_1_setup(&test_fixture, TEST_IDX); + + tdata->f = f; + + if (tdata->f->test_idx == 1) + tdata->acd_timeout_msec = 0; + else + tdata->acd_timeout_msec = L3IPV4LL_ACD_TIMEOUT_MSEC; + + _test_l3_ipv4ll_maybe_add_addr_4(tdata, 0, 4, &tdata->has_addr4_101, "192.168.133.101"); + + l3cfg0 = _netns_access_l3cfg(f->netns, f->ifindex0); + + g_signal_connect(l3cfg0, + NM_L3CFG_SIGNAL_NOTIFY, + G_CALLBACK(_test_l3_ipv4ll_signal_notify), + tdata); + + l3ipv4ll = nm_l3_ipv4ll_new(l3cfg0); + + tdata->l3ipv4ll = l3ipv4ll; + + g_assert_cmpint(nm_l3_ipv4ll_get_ifindex(l3ipv4ll), ==, f->ifindex0); + g_assert_cmpint(nm_l3_ipv4ll_get_state(l3ipv4ll), ==, NM_L3_IPV4LL_STATE_DISABLED); + g_assert_cmpint(nm_l3_ipv4ll_get_addr(l3ipv4ll), ==, 0u); + + if (tdata->f->test_idx == 1) { + if (nmtst_get_rand_one_case_in(2)) + l3ipv4ll_reg = nm_l3_ipv4ll_register_new(l3ipv4ll, tdata->acd_timeout_msec); + } else + l3ipv4ll_reg = nm_l3_ipv4ll_register_new(l3ipv4ll, tdata->acd_timeout_msec); + + g_assert(tdata->acd_timeout_msec == 0 || l3ipv4ll_reg); + g_assert(!l3ipv4ll_reg || l3ipv4ll == nm_l3_ipv4ll_register_get_instance(l3ipv4ll_reg)); + + if (tdata->acd_timeout_msec == 0) { + g_assert_cmpint(nm_l3_ipv4ll_get_state(l3ipv4ll), ==, NM_L3_IPV4LL_STATE_DISABLED); + g_assert_cmpint(nm_l3_ipv4ll_get_addr(l3ipv4ll), ==, 0u); + } else { + g_assert_cmpint(nm_l3_ipv4ll_get_state(l3ipv4ll), ==, NM_L3_IPV4LL_STATE_PROBING); + if (f->test_idx == 1) { + g_assert_cmpint(nm_l3_ipv4ll_get_addr(l3ipv4ll), + ==, + nmtst_inet4_from_string("169.254.30.158")); + } else { + g_assert_cmpint(nm_l3_ipv4ll_get_addr(l3ipv4ll), + ==, + nmtst_inet4_from_string("169.254.17.45")); + } + g_assert(nm_l3_ipv4ll_get_l3cd(l3ipv4ll)); + } + + _test_l3_ipv4ll_maybe_add_addr_4(tdata, 0, 4, &tdata->has_addr4_101, "192.168.133.101"); + + if (tdata->f->test_idx == 2 && nmtst_get_rand_one_case_in(3)) { + in_addr_t a = nm_l3_ipv4ll_get_addr(l3ipv4ll); + + g_assert(nm_utils_ip4_address_is_link_local(a)); + _test_l3_ipv4ll_maybe_add_addr_4(tdata, + tdata->f->ifindex1, + 2, + &tdata->add_conflict_done, + _nm_utils_inet4_ntop(a, sbuf_addr)); + g_assert_cmpint(tdata->f->hwaddr1.len, ==, sizeof(NMEtherAddr)); + acd_defender_2 = + nmtstp_acd_defender_new(tdata->f->ifindex1, a, &tdata->f->hwaddr1.ether_addr); + } + + start_time_msec = nm_utils_get_monotonic_timestamp_msec(); + total_poll_time_msec = + (L3IPV4LL_ACD_TIMEOUT_MSEC * 3 / 2) + (nmtst_get_rand_uint32() % L3IPV4LL_ACD_TIMEOUT_MSEC); + _LOGT("poll 1 start (wait %" G_GINT64_FORMAT " msec)", total_poll_time_msec); + while (TRUE) { + gint64 next_timeout_msec; + + next_timeout_msec = + start_time_msec + total_poll_time_msec - nm_utils_get_monotonic_timestamp_msec(); + if (next_timeout_msec <= 0) + break; + + next_timeout_msec = NM_MIN(next_timeout_msec, nmtst_get_rand_uint32() % 1000u); + nmtst_main_context_iterate_until(NULL, next_timeout_msec, FALSE); + _LOGT("poll 1 intermezzo"); + + _test_l3_ipv4ll_maybe_add_addr_4(tdata, + 0, + 1 + total_poll_time_msec / 1000, + &tdata->has_addr4_101, + "192.168.133.101"); + + if (tdata->addr_commit == 1 && !tdata->add_conflict_checked) { + tdata->add_conflict_checked = TRUE; + _test_l3_ipv4ll_maybe_add_addr_4( + tdata, + tdata->f->ifindex1, + 2, + &tdata->add_conflict_done, + _nm_utils_inet4_ntop(tdata->addr_commit_addr, sbuf_addr)); + if (tdata->add_conflict_done) + total_poll_time_msec += L3IPV4LL_ACD_TIMEOUT_MSEC / 2; + g_assert_cmpint(tdata->f->hwaddr1.len, ==, sizeof(NMEtherAddr)); + acd_defender_2 = nmtstp_acd_defender_new(tdata->f->ifindex1, + tdata->addr_commit_addr, + &tdata->f->hwaddr1.ether_addr); + } + } + _LOGT("poll 1 end"); + + if (tdata->addr_commit || nmtst_get_rand_bool()) { + nm_l3cfg_remove_config_all(nm_l3_ipv4ll_get_l3cfg(l3ipv4ll), + TEST_L3_IPV4LL_TAG(tdata, 1), + FALSE); + } + + nmtstp_acd_defender_destroy(g_steal_pointer(&acd_defender_1)); + nmtstp_acd_defender_destroy(g_steal_pointer(&acd_defender_2)); + + nm_l3cfg_commit_type_unregister(l3cfg0, g_steal_pointer(&tdata->l3cfg_commit_type_1)); + + g_signal_handlers_disconnect_by_func(l3cfg0, G_CALLBACK(_test_l3_ipv4ll_signal_notify), tdata); +} + +/*****************************************************************************/ + +NMTstpSetupFunc const _nmtstp_setup_platform_func = nm_linux_platform_setup; + +void +_nmtstp_init_tests(int *argc, char ***argv) +{ + nmtst_init_with_logging(argc, argv, "ERR", "ALL"); +} + +void +_nmtstp_setup_tests(void) +{ + g_test_add_data_func("/l3cfg/1", GINT_TO_POINTER(1), test_l3cfg); + g_test_add_data_func("/l3cfg/2", GINT_TO_POINTER(2), test_l3cfg); + g_test_add_data_func("/l3cfg/3", GINT_TO_POINTER(3), test_l3cfg); + g_test_add_data_func("/l3cfg/4", GINT_TO_POINTER(4), test_l3cfg); + g_test_add_data_func("/l3-ipv4ll/1", GINT_TO_POINTER(1), test_l3_ipv4ll); + g_test_add_data_func("/l3-ipv4ll/2", GINT_TO_POINTER(2), test_l3_ipv4ll); +} diff --git a/src/tests/test-secret-agent.py b/src/core/tests/test-secret-agent.py index 46f82b34..46f82b34 100755 --- a/src/tests/test-secret-agent.py +++ b/src/core/tests/test-secret-agent.py diff --git a/src/tests/test-systemd.c b/src/core/tests/test-systemd.c index 54cca509..03576c13 100644 --- a/src/tests/test-systemd.c +++ b/src/core/tests/test-systemd.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2016 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/systemd/nm-default-systemd.h" #include "systemd/nm-sd.h" #include "systemd/nm-sd-utils-shared.h" diff --git a/src/tests/test-utils.c b/src/core/tests/test-utils.c index 4635d982..1d562bde 100644 --- a/src/tests/test-utils.c +++ b/src/core/tests/test-utils.c @@ -1,11 +1,12 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2015 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include <arpa/inet.h> +#include <linux/if_ether.h> #include "nm-test-utils-core.h" diff --git a/src/tests/test-wired-defname.c b/src/core/tests/test-wired-defname.c index 6e214549..f810c56f 100644 --- a/src/tests/test-wired-defname.c +++ b/src/core/tests/test-wired-defname.c @@ -1,9 +1,9 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2010 Red Hat, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-simple-connection.h" #include "nm-setting-connection.h" diff --git a/src/vpn/nm-vpn-connection.c b/src/core/vpn/nm-vpn-connection.c index 68c66af7..02831b08 100644 --- a/src/vpn/nm-vpn-connection.c +++ b/src/core/vpn/nm-vpn-connection.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-vpn-connection.h" @@ -862,22 +862,22 @@ nm_vpn_connection_new(NMSettingsConnection * settings_connection, g_return_val_if_fail(NM_IS_DEVICE(parent_device), NULL); g_return_val_if_fail(specific_object, NULL); - return (NMVpnConnection *) g_object_new(NM_TYPE_VPN_CONNECTION, - NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, - settings_connection, - NM_ACTIVE_CONNECTION_INT_DEVICE, - parent_device, - NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, - specific_object, - NM_ACTIVE_CONNECTION_INT_SUBJECT, - subject, - NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, - activation_reason, - NM_ACTIVE_CONNECTION_VPN, - TRUE, - NM_ACTIVE_CONNECTION_STATE_FLAGS, - (guint) initial_state_flags, - NULL); + return g_object_new(NM_TYPE_VPN_CONNECTION, + NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, + settings_connection, + NM_ACTIVE_CONNECTION_INT_DEVICE, + parent_device, + NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, + specific_object, + NM_ACTIVE_CONNECTION_INT_SUBJECT, + subject, + NM_ACTIVE_CONNECTION_INT_ACTIVATION_REASON, + activation_reason, + NM_ACTIVE_CONNECTION_VPN, + TRUE, + NM_ACTIVE_CONNECTION_STATE_FLAGS, + (guint) initial_state_flags, + NULL); } const char * diff --git a/src/vpn/nm-vpn-connection.h b/src/core/vpn/nm-vpn-connection.h index 9cf80a1e..66ec7eec 100644 --- a/src/vpn/nm-vpn-connection.h +++ b/src/core/vpn/nm-vpn-connection.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/vpn/nm-vpn-manager.c b/src/core/vpn/nm-vpn-manager.c index 607ad7f3..53fe58dd 100644 --- a/src/vpn/nm-vpn-manager.c +++ b/src/core/vpn/nm-vpn-manager.c @@ -1,10 +1,10 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ -#include "nm-default.h" +#include "src/core/nm-default-daemon.h" #include "nm-vpn-manager.h" diff --git a/src/vpn/nm-vpn-manager.h b/src/core/vpn/nm-vpn-manager.h index 5f24df25..41ecb8d2 100644 --- a/src/vpn/nm-vpn-manager.h +++ b/src/core/vpn/nm-vpn-manager.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright (C) 2005 - 2011 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. diff --git a/src/devices/bluetooth/meson.build b/src/devices/bluetooth/meson.build deleted file mode 100644 index 638a01a2..00000000 --- a/src/devices/bluetooth/meson.build +++ /dev/null @@ -1,60 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nm-bluez-manager.c', - 'nm-bt-error.c', - 'nm-device-bt.c', -) - -deps = [ - daemon_nm_default_dep, - libnm_wwan_dep, -] - -if enable_bluez5_dun - sources += files('nm-bluez5-dun.c') - - deps += bluez5_dep -endif - -libnm_device_plugin_bluetooth_static = static_library( - 'nm-device-plugin-bluetooth-static', - sources: sources, - dependencies: deps, - c_args: daemon_c_flags, -) - -libnm_device_plugin_bluetooth_static_dep = declare_dependency( - link_whole: libnm_device_plugin_bluetooth_static, -) - -deps += libnm_device_plugin_bluetooth_static_dep - -libnm_device_plugin_bluetooth = shared_module( - 'nm-device-plugin-bluetooth', - dependencies: deps, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_plugindir, - install_rpath: nm_plugindir, -) - -core_plugins += libnm_device_plugin_bluetooth - -test( - 'check-local-devices-bluetooth', - check_exports, - args: [libnm_device_plugin_bluetooth.full_path(), linker_script_devices], -) - -if enable_tests - test_unit = 'nm-bt-test' - - executable( - test_unit, - 'tests/' + test_unit + '.c', - dependencies: [ libnetwork_manager_test_dep, deps ], - c_args: test_c_flags, - ) -endif diff --git a/src/devices/ovs/meson.build b/src/devices/ovs/meson.build deleted file mode 100644 index 8457e68a..00000000 --- a/src/devices/ovs/meson.build +++ /dev/null @@ -1,33 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nm-device-ovs-bridge.c', - 'nm-device-ovs-interface.c', - 'nm-device-ovs-port.c', - 'nm-ovsdb.c', - 'nm-ovs-factory.c', -) - -deps = [ - daemon_nm_default_dep, - jansson_dep, -] - -libnm_device_plugin_ovs = shared_module( - 'nm-device-plugin-ovs', - sources: sources, - dependencies: deps, - c_args: daemon_c_flags, - link_args: ldflags_linker_script_devices, - link_depends: linker_script_devices, - install: true, - install_dir: nm_plugindir, -) - -core_plugins += libnm_device_plugin_ovs - -test( - 'check-local-devices-ovs', - check_exports, - args: [libnm_device_plugin_ovs.full_path(), linker_script_devices], -) diff --git a/src/dhcp/meson.build b/src/dhcp/meson.build deleted file mode 100644 index 67f055d9..00000000 --- a/src/dhcp/meson.build +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -name = 'nm-dhcp-helper' - -c_flags = [ - '-DG_LOG_DOMAIN="@0@"'.format(name), - '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_GLIB', -] - -executable( - name, - name + '.c', - dependencies: glib_nm_default_dep, - c_args: c_flags, - link_args: ldflags_linker_script_binary, - link_depends: linker_script_binary, - install: true, - install_dir: nm_libexecdir, -) - -if enable_tests - subdir('tests') -endif diff --git a/src/initrd/meson.build b/src/initrd/meson.build deleted file mode 100644 index c056f3c2..00000000 --- a/src/initrd/meson.build +++ /dev/null @@ -1,37 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'nmi-cmdline-reader.c', - 'nmi-dt-reader.c', - 'nmi-ibft-reader.c', -) - -libnmi_core = static_library( - 'nmi-core', - sources: sources, - dependencies: daemon_nm_default_dep, - c_args: daemon_c_flags, -) - -name = 'nm-initrd-generator' - -links = [ - libnetwork_manager_base, - libnmi_core, -] - -executable( - name, - name + '.c', - dependencies: daemon_nm_default_dep, - c_args: daemon_c_flags, - link_with: links, - link_args: ldflags_linker_script_binary, - link_depends: linker_script_binary, - install: true, - install_dir: nm_libexecdir, -) - -if enable_tests - subdir('tests') -endif diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 667a6a2c..00000000 --- a/src/meson.build +++ /dev/null @@ -1,318 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -src_inc = include_directories('.') - -daemon_nm_default_dep = declare_dependency( - sources: libnm_core_enum_sources[1], - include_directories: src_inc, - dependencies: libnm_core_nm_default_dep, -) - -install_data( - 'org.freedesktop.NetworkManager.conf', - install_dir: dbus_conf_dir, -) - -subdir('systemd') - -core_plugins = [] - -daemon_c_flags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_DAEMON'] - -sources = files( - 'dhcp/nm-dhcp-client.c', - 'dhcp/nm-dhcp-manager.c', - 'dhcp/nm-dhcp-nettools.c', - 'dhcp/nm-dhcp-systemd.c', - 'dhcp/nm-dhcp-utils.c', - 'dhcp/nm-dhcp-options.c', - 'ndisc/nm-lndp-ndisc.c', - 'ndisc/nm-ndisc.c', - 'platform/nm-netlink.c', - 'platform/wifi/nm-wifi-utils-nl80211.c', - 'platform/wifi/nm-wifi-utils.c', - 'platform/wpan/nm-wpan-utils.c', - 'platform/nm-linux-platform.c', - 'platform/nm-platform.c', - 'platform/nm-platform-utils.c', - 'platform/nmp-netns.c', - 'platform/nmp-object.c', - 'platform/nmp-rules-manager.c', - 'main-utils.c', - 'NetworkManagerUtils.c', - 'nm-core-utils.c', - 'nm-dbus-object.c', - 'nm-dbus-utils.c', - 'nm-netns.c', - 'nm-l3-config-data.c', - 'nm-l3cfg.c', - 'nm-ip-config.c', - 'nm-ip4-config.c', - 'nm-ip6-config.c', - 'nm-logging.c', -) - -deps = [ - daemon_nm_default_dep, - libn_dhcp4_dep, - libnm_keyfile_dep, - libnm_core_dep, - libnm_systemd_shared_dep, - libnm_udev_aux_dep, - libsystemd_dep, - libudev_dep, -] - -if enable_wext - sources += files('platform/wifi/nm-wifi-utils-wext.c') -endif - -libnetwork_manager_base = static_library( - nm_name + 'Base', - sources: sources, - dependencies: deps, - c_args: daemon_c_flags, -) - -sources = files( - 'devices/nm-acd-manager.c', - 'devices/nm-device-6lowpan.c', - 'devices/nm-device-bond.c', - 'devices/nm-device-bridge.c', - 'devices/nm-device.c', - 'devices/nm-device-dummy.c', - 'devices/nm-device-ethernet.c', - 'devices/nm-device-ethernet-utils.c', - 'devices/nm-device-factory.c', - 'devices/nm-device-generic.c', - 'devices/nm-device-infiniband.c', - 'devices/nm-device-ip-tunnel.c', - 'devices/nm-device-macsec.c', - 'devices/nm-device-macvlan.c', - 'devices/nm-device-ppp.c', - 'devices/nm-device-tun.c', - 'devices/nm-device-veth.c', - 'devices/nm-device-vlan.c', - 'devices/nm-device-vrf.c', - 'devices/nm-device-vxlan.c', - 'devices/nm-device-wireguard.c', - 'devices/nm-device-wpan.c', - 'devices/nm-lldp-listener.c', - 'dhcp/nm-dhcp-dhclient.c', - 'dhcp/nm-dhcp-dhclient-utils.c', - 'dhcp/nm-dhcp-dhcpcanon.c', - 'dhcp/nm-dhcp-dhcpcd.c', - 'dhcp/nm-dhcp-listener.c', - 'dns/nm-dns-dnsmasq.c', - 'dns/nm-dns-manager.c', - 'dns/nm-dns-plugin.c', - 'dns/nm-dns-systemd-resolved.c', - 'dns/nm-dns-unbound.c', - 'dnsmasq/nm-dnsmasq-manager.c', - 'dnsmasq/nm-dnsmasq-utils.c', - 'ppp/nm-ppp-manager-call.c', - 'settings/plugins/keyfile/nms-keyfile-storage.c', - 'settings/plugins/keyfile/nms-keyfile-plugin.c', - 'settings/plugins/keyfile/nms-keyfile-reader.c', - 'settings/plugins/keyfile/nms-keyfile-utils.c', - 'settings/plugins/keyfile/nms-keyfile-writer.c', - 'settings/nm-agent-manager.c', - 'settings/nm-secret-agent.c', - 'settings/nm-settings.c', - 'settings/nm-settings-connection.c', - 'settings/nm-settings-plugin.c', - 'settings/nm-settings-storage.c', - 'settings/nm-settings-utils.c', - 'supplicant/nm-supplicant-config.c', - 'supplicant/nm-supplicant-interface.c', - 'supplicant/nm-supplicant-manager.c', - 'supplicant/nm-supplicant-settings-verify.c', - 'vpn/nm-vpn-connection.c', - 'vpn/nm-vpn-manager.c', - 'nm-active-connection.c', - 'nm-act-request.c', - 'nm-audit-manager.c', - 'nm-auth-manager.c', - 'nm-auth-utils.c', - 'nm-dbus-manager.c', - 'nm-checkpoint.c', - 'nm-checkpoint-manager.c', - 'nm-config.c', - 'nm-config-data.c', - 'nm-connectivity.c', - 'nm-dcb.c', - 'nm-dhcp-config.c', - 'nm-dispatcher.c', - 'nm-firewall-manager.c', - 'nm-hostname-manager.c', - 'nm-keep-alive.c', - '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', -) - -nm_deps = [ - daemon_nm_default_dep, - dl_dep, - libn_acd_dep, - libndp_dep, - libudev_dep, - logind_dep, -] - -nm_links = [ - libnetwork_manager_base, - libnm_systemd_core, - libnm_systemd_shared, -] - -if enable_concheck - nm_deps += libcurl_dep -endif - -if enable_libaudit - nm_deps += libaudit_dep -endif - -if enable_libpsl - nm_deps += libpsl_dep -endif - -if enable_selinux - nm_deps += selinux_dep -endif - -libnetwork_manager = static_library( - nm_name, - sources: sources, - dependencies: nm_deps, - c_args: daemon_c_flags, - link_with: nm_links, -) - -executable( - 'nm-iface-helper', - 'nm-iface-helper.c', - dependencies: [ - daemon_nm_default_dep, - dl_dep, - libndp_dep, - libudev_dep, - libn_acd_dep, - ], - c_args: daemon_c_flags, - link_with: nm_links, - link_args: ldflags_linker_script_binary, - link_depends: linker_script_binary, - install: true, - install_dir: nm_libexecdir, -) - -if enable_tests - test_c_flags = daemon_c_flags + ['-DNETWORKMANAGER_COMPILATION_TEST'] - if require_root_tests - test_c_flags += ['-DREQUIRE_ROOT_TESTS=1'] - endif - - sources = files( - 'ndisc/nm-fake-ndisc.c', - 'platform/tests/test-common.c', - 'platform/nm-fake-platform.c', - ) - - libnetwork_manager_test = static_library( - nm_name + 'Test', - sources: sources, - dependencies: daemon_nm_default_dep, - c_args: test_c_flags, - link_with: libnetwork_manager, - ) - - libnetwork_manager_test_dep = declare_dependency( - dependencies: daemon_nm_default_dep, - link_with: libnetwork_manager_test, - ) - - subdir('dnsmasq/tests') - subdir('ndisc/tests') - subdir('platform/tests') - subdir('supplicant/tests') - subdir('tests') -endif - -subdir('dhcp') - -if enable_ppp - subdir('ppp') -endif - -subdir('devices') -subdir('initrd') -subdir('settings/plugins') - -# NetworkManager binary - -create_exports_networkmanager = join_paths(source_root, 'tools', 'create-exports-NetworkManager.sh') -symbol_map_name = 'NetworkManager.ver' - -# libNetworkManager.a, as built by meson doesn't contain all symbols -# from libNetworkManagerBase.a and other static libraries, unless we -# add dependencies with link_whole, only supported in meson >= 0.46. -# Create an executable with full symbols that we use in place of the -# library to enumerate the symbols. -network_manager_all_sym = executable( - 'NetworkManager-all-sym', - 'main.c', - dependencies: nm_deps, - c_args: daemon_c_flags, - link_args: '-Wl,--no-gc-sections', - link_whole: [libnetwork_manager, libnetwork_manager_base, libnm_core], -) - -# this uses symbols from nm-full-symbols instead of libNetworkManager.a -ver_script = custom_target( - symbol_map_name, - output: symbol_map_name, - depends: [network_manager_all_sym, core_plugins], - command: [create_exports_networkmanager, '--called-from-build', source_root], -) - -ldflags = [ - '-rdynamic', - '-Wl,--version-script,@0@'.format(ver_script.full_path()), -] - -network_manager = executable( - nm_name, - 'main.c', - dependencies: nm_deps, - c_args: daemon_c_flags, - link_with: libnetwork_manager, - link_args: ldflags, - link_depends: ver_script, - install: true, - install_dir: nm_sbindir, -) - -if enable_tests - foreach plugin: core_plugins - plugin_path = plugin.full_path() - - test( - 'sym/' + plugin_path.split('/')[-1], - network_manager, - args: '--version', - env: ['LD_BIND_NOW=1', 'LD_PRELOAD=' + plugin_path], - ) - endforeach -endif - -test( - 'check-config-options', - find_program(join_paths(source_root, 'tools', 'check-config-options.sh')), - args: source_root, -) diff --git a/src/ndisc/tests/test-ndisc-fake.c b/src/ndisc/tests/test-ndisc-fake.c deleted file mode 100644 index dfb0b37b..00000000 --- a/src/ndisc/tests/test-ndisc-fake.c +++ /dev/null @@ -1,538 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include <syslog.h> - -#include "ndisc/nm-ndisc.h" -#include "ndisc/nm-fake-ndisc.h" - -#include "platform/nm-fake-platform.h" - -#include "nm-test-utils-core.h" - -static NMFakeNDisc * -ndisc_new(void) -{ - NMNDisc * ndisc; - const int ifindex = 1; - const char * ifname = nm_platform_link_get_name(NM_PLATFORM_GET, ifindex); - NMUtilsIPv6IfaceId iid = {}; - - ndisc = nm_fake_ndisc_new(ifindex, ifname); - iid.id_u8[7] = 1; - nm_ndisc_set_iid(ndisc, iid); - g_assert(ndisc); - return NM_FAKE_NDISC(ndisc); -} - -static void -match_gateway(const NMNDiscData *rdata, - guint idx, - const char * addr, - guint32 ts, - guint32 lt, - NMIcmpv6RouterPref pref) -{ - const NMNDiscGateway *gw; - char buf[INET6_ADDRSTRLEN]; - - g_assert(rdata); - g_assert_cmpint(idx, <, rdata->gateways_n); - g_assert(rdata->gateways); - - gw = &rdata->gateways[idx]; - - g_assert_cmpstr(inet_ntop(AF_INET6, &gw->address, buf, sizeof(buf)), ==, addr); - g_assert_cmpint(gw->timestamp, ==, ts); - g_assert_cmpint(gw->lifetime, ==, lt); - g_assert_cmpint(gw->preference, ==, pref); -} - -#define match_address(rdata, idx, addr, ts, lt, pref) \ - G_STMT_START \ - { \ - const NMNDiscData * _rdata = (rdata); \ - guint _idx = (idx); \ - const NMNDiscAddress *_a; \ - guint _ts = (ts); \ - \ - g_assert(_rdata); \ - g_assert_cmpint(_idx, <, _rdata->addresses_n); \ - g_assert(_rdata->addresses); \ - \ - _a = &_rdata->addresses[_idx]; \ - \ - nmtst_assert_ip6_address(&_a->address, (addr)); \ - g_assert_cmpint(_a->timestamp, <=, _ts + 1); \ - g_assert_cmpint((int) _a->timestamp, >=, (int) _ts - 1); \ - g_assert_cmpint(_a->timestamp + _a->lifetime, ==, _ts + (lt)); \ - g_assert_cmpint(_a->timestamp + _a->preferred, ==, _ts + (pref)); \ - } \ - G_STMT_END - -#define match_route(rdata, idx, nw, pl, gw, ts, lt, pref) \ - G_STMT_START \ - { \ - const NMNDiscData * _rdata = (rdata); \ - guint _idx = (idx); \ - const NMNDiscRoute *_r; \ - int _plen = (pl); \ - \ - g_assert(_rdata); \ - g_assert_cmpint(_idx, <, _rdata->routes_n); \ - g_assert(_rdata->routes); \ - g_assert(_plen > 0 && _plen <= 128); \ - \ - _r = &_rdata->routes[idx]; \ - \ - nmtst_assert_ip6_address(&_r->network, (nw)); \ - g_assert_cmpint((int) _r->plen, ==, _plen); \ - nmtst_assert_ip6_address(&_r->gateway, (gw)); \ - g_assert_cmpint(_r->timestamp, ==, (ts)); \ - g_assert_cmpint(_r->lifetime, ==, (lt)); \ - g_assert_cmpint(_r->preference, ==, (pref)); \ - } \ - G_STMT_END - -static void -match_dns_server(const NMNDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt) -{ - const NMNDiscDNSServer *dns; - char buf[INET6_ADDRSTRLEN]; - - g_assert(rdata); - g_assert_cmpint(idx, <, rdata->dns_servers_n); - g_assert(rdata->dns_servers); - - dns = &rdata->dns_servers[idx]; - - g_assert_cmpstr(inet_ntop(AF_INET6, &dns->address, buf, sizeof(buf)), ==, addr); - g_assert_cmpint(dns->timestamp, ==, ts); - g_assert_cmpint(dns->lifetime, ==, lt); -} - -static void -match_dns_domain(const NMNDiscData *rdata, guint idx, const char *domain, guint32 ts, guint32 lt) -{ - const NMNDiscDNSDomain *dns; - - g_assert(rdata); - g_assert_cmpint(idx, <, rdata->dns_domains_n); - g_assert(rdata->dns_domains); - - dns = &rdata->dns_domains[idx]; - - g_assert_cmpstr(dns->domain, ==, domain); - g_assert_cmpint(dns->timestamp, ==, ts); - g_assert_cmpint(dns->lifetime, ==, lt); -} - -typedef struct { - GMainLoop *loop; - guint counter; - guint rs_counter; - guint32 timestamp1; - guint32 first_solicit; - guint32 timeout_id; -} TestData; - -static void -test_simple_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) -{ - NMNDiscConfigMap changed = changed_int; - - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS - | NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES - | NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS - | NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU); - g_assert_cmpint(rdata->dhcp_level, ==, NM_NDISC_DHCP_LEVEL_OTHERCONF); - match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10); - match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10); - match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10); - match_dns_domain(rdata, 0, "foobar.com", data->timestamp1, 10); - - g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); - data->counter++; - g_main_loop_quit(data->loop); -} - -static void -test_simple(void) -{ - NMFakeNDisc *ndisc = ndisc_new(); - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now}; - guint id; - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_OTHERCONF, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10); - nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 10); - nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 10); - - g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_simple_changed), &data); - - nm_ndisc_start(NM_NDISC(ndisc)); - g_main_loop_run(data.loop); - g_assert_cmpint(data.counter, ==, 1); - - g_object_unref(ndisc); - g_main_loop_unref(data.loop); -} - -static void -test_everything_rs_sent(NMNDisc *ndisc, TestData *data) -{ - g_assert_cmpint(data->rs_counter, ==, 0); - data->rs_counter++; -} - -static void -test_everything_changed(NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data) -{ - NMNDiscConfigMap changed = changed_int; - - if (data->counter == 0) { - g_assert_cmpint(data->rs_counter, ==, 1); - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_DHCP_LEVEL | NM_NDISC_CONFIG_GATEWAYS - | NM_NDISC_CONFIG_ADDRESSES | NM_NDISC_CONFIG_ROUTES - | NM_NDISC_CONFIG_DNS_SERVERS | NM_NDISC_CONFIG_DNS_DOMAINS - | NM_NDISC_CONFIG_HOP_LIMIT | NM_NDISC_CONFIG_MTU); - match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10); - match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10); - match_dns_server(rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10); - match_dns_domain(rdata, 0, "foobar.com", data->timestamp1, 10); - } else if (data->counter == 1) { - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES - | NM_NDISC_CONFIG_ROUTES | NM_NDISC_CONFIG_DNS_SERVERS - | NM_NDISC_CONFIG_DNS_DOMAINS); - - g_assert_cmpint(rdata->gateways_n, ==, 1); - match_gateway(rdata, 0, "fe80::2", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - g_assert_cmpint(rdata->addresses_n, ==, 2); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 0); - match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1, 10, 10); - g_assert_cmpint(rdata->routes_n, ==, 1); - match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1, 10, 10); - g_assert_cmpint(rdata->dns_servers_n, ==, 1); - match_dns_server(rdata, 0, "2001:db8:c:c::2", data->timestamp1, 10); - g_assert_cmpint(rdata->dns_domains_n, ==, 1); - match_dns_domain(rdata, 0, "foobar2.com", data->timestamp1, 10); - - g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); - g_main_loop_quit(data->loop); - } else - g_assert_not_reached(); - - data->counter++; -} - -static void -test_everything(void) -{ - NMFakeNDisc *ndisc = ndisc_new(); - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now}; - guint id; - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10); - nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 10); - nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 10); - - /* expire everything from the first RA in the second */ - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 0, NM_ICMPV6_ROUTER_PREF_MEDIUM); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 0, 0, 0); - nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 0); - nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar.com", now, 0); - - /* and add some new stuff */ - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10); - nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::2", now, 10); - nm_fake_ndisc_add_dns_domain(ndisc, id, "foobar2.com", now, 10); - - g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_everything_changed), &data); - g_signal_connect(ndisc, NM_FAKE_NDISC_RS_SENT, G_CALLBACK(test_everything_rs_sent), &data); - - nm_ndisc_start(NM_NDISC(ndisc)); - g_main_loop_run(data.loop); - g_assert_cmpint(data.counter, ==, 2); - g_assert_cmpint(data.rs_counter, ==, 1); - - g_object_unref(ndisc); - g_main_loop_unref(data.loop); -} - -static void -test_preference_order_cb(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) -{ - NMNDiscConfigMap changed = changed_int; - - if (data->counter == 1) { - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES - | NM_NDISC_CONFIG_ROUTES); - - g_assert_cmpint(rdata->gateways_n, ==, 2); - match_gateway(rdata, 0, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_HIGH); - match_gateway(rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_LOW); - g_assert_cmpint(rdata->addresses_n, ==, 2); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10); - match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10); - g_assert_cmpint(rdata->routes_n, ==, 2); - match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10); - match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5); - - g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); - g_main_loop_quit(data->loop); - } - - data->counter++; -} - -static void -test_preference_order(void) -{ - NMFakeNDisc *ndisc = ndisc_new(); - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now}; - guint id; - - /* Test insertion order of gateways */ - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_HIGH); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5); - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", ++now, 10, NM_ICMPV6_ROUTER_PREF_LOW); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10); - - g_signal_connect(ndisc, NM_NDISC_CONFIG_RECEIVED, G_CALLBACK(test_preference_order_cb), &data); - - nm_ndisc_start(NM_NDISC(ndisc)); - g_main_loop_run(data.loop); - g_assert_cmpint(data.counter, ==, 2); - - g_object_unref(ndisc); - g_main_loop_unref(data.loop); -} - -static void -test_preference_changed_cb(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) -{ - NMNDiscConfigMap changed = changed_int; - - if (data->counter == 1) { - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES - | NM_NDISC_CONFIG_ROUTES); - g_assert_cmpint(rdata->gateways_n, ==, 2); - match_gateway(rdata, 0, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - match_gateway(rdata, 1, "fe80::1", data->timestamp1, 10, NM_ICMPV6_ROUTER_PREF_LOW); - g_assert_cmpint(rdata->addresses_n, ==, 2); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10); - match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10); - g_assert_cmpint(rdata->routes_n, ==, 2); - match_route(rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10); - match_route(rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5); - } else if (data->counter == 2) { - g_assert_cmpint(changed, - ==, - NM_NDISC_CONFIG_GATEWAYS | NM_NDISC_CONFIG_ADDRESSES - | NM_NDISC_CONFIG_ROUTES); - - g_assert_cmpint(rdata->gateways_n, ==, 2); - match_gateway(rdata, 0, "fe80::1", data->timestamp1 + 2, 10, NM_ICMPV6_ROUTER_PREF_HIGH); - match_gateway(rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - g_assert_cmpint(rdata->addresses_n, ==, 2); - match_address(rdata, 0, "2001:db8:a:a::1", data->timestamp1 + 3, 9, 9); - match_address(rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10); - g_assert_cmpint(rdata->routes_n, ==, 2); - match_route(rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1 + 2, 10, 15); - match_route(rdata, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10); - - g_assert(nm_fake_ndisc_done(NM_FAKE_NDISC(ndisc))); - g_main_loop_quit(data->loop); - } - - data->counter++; -} - -static void -test_preference_changed(void) -{ - NMFakeNDisc *ndisc = ndisc_new(); - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now}; - guint id; - - /* Test that when a low-preference and medium gateway send advertisements, - * that if the low-preference gateway switches to high-preference, we do - * not get duplicates in the gateway list. - */ - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_LOW); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5); - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::2", ++now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10); - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", ++now, 10, NM_ICMPV6_ROUTER_PREF_HIGH); - nm_fake_ndisc_add_prefix(ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 15); - - g_signal_connect(ndisc, - NM_NDISC_CONFIG_RECEIVED, - G_CALLBACK(test_preference_changed_cb), - &data); - - nm_ndisc_start(NM_NDISC(ndisc)); - g_main_loop_run(data.loop); - g_assert_cmpint(data.counter, ==, 3); - - g_object_unref(ndisc); - g_main_loop_unref(data.loop); -} - -static void -test_dns_solicit_loop_changed(NMNDisc * ndisc, - const NMNDiscData *rdata, - guint changed_int, - TestData * data) -{ - data->counter++; -} - -static gboolean -success_timeout(TestData *data) -{ - data->timeout_id = 0; - g_main_loop_quit(data->loop); - return G_SOURCE_REMOVE; -} - -static void -test_dns_solicit_loop_rs_sent(NMFakeNDisc *ndisc, TestData *data) -{ - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - guint id; - - if (data->rs_counter > 0 && data->rs_counter < 6) { - if (data->rs_counter == 1) { - data->first_solicit = now; - /* Kill the test after 10 seconds if it hasn't failed yet */ - data->timeout_id = g_timeout_add_seconds(10, (GSourceFunc) success_timeout, data); - } - - /* On all but the first solicitation, which should be triggered by the - * DNS servers reaching 1/2 lifetime, emit a new RA without the DNS - * servers again. - */ - id = nm_fake_ndisc_add_ra(ndisc, 0, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_MEDIUM); - - nm_fake_ndisc_emit_new_ras(ndisc); - } else if (data->rs_counter >= 6) { - /* Fail if we've sent too many solicitations in the past 4 seconds */ - g_assert_cmpint(now - data->first_solicit, >, 4); - g_source_remove(data->timeout_id); - g_main_loop_quit(data->loop); - } - data->rs_counter++; -} - -static void -test_dns_solicit_loop(void) -{ - NMFakeNDisc *ndisc = ndisc_new(); - guint32 now = nm_utils_get_monotonic_timestamp_sec(); - TestData data = {g_main_loop_new(NULL, FALSE), 0, 0, now, 0}; - guint id; - - /* Ensure that no solicitation loop happens when DNS servers or domains - * stop being sent in advertisements. This can happen if two routers - * send RAs, but the one sending DNS info stops responding, or if one - * router removes the DNS info from the RA without zero-lifetiming them - * first. - */ - - id = nm_fake_ndisc_add_ra(ndisc, 1, NM_NDISC_DHCP_LEVEL_NONE, 4, 1500); - g_assert(id); - nm_fake_ndisc_add_gateway(ndisc, id, "fe80::1", now, 10, NM_ICMPV6_ROUTER_PREF_LOW); - nm_fake_ndisc_add_dns_server(ndisc, id, "2001:db8:c:c::1", now, 6); - - g_signal_connect(ndisc, - NM_NDISC_CONFIG_RECEIVED, - G_CALLBACK(test_dns_solicit_loop_changed), - &data); - g_signal_connect(ndisc, - NM_FAKE_NDISC_RS_SENT, - G_CALLBACK(test_dns_solicit_loop_rs_sent), - &data); - - nm_ndisc_start(NM_NDISC(ndisc)); - g_main_loop_run(data.loop); - g_assert_cmpint(data.counter, ==, 3); - - g_object_unref(ndisc); - g_main_loop_unref(data.loop); -} - -NMTST_DEFINE(); - -int -main(int argc, char **argv) -{ - nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT"); - - if (nmtst_test_quick()) { - g_print("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", - g_get_prgname() ?: "test-ndisc-fake"); - return g_test_run(); - } - - nm_fake_platform_setup(); - - g_test_add_func("/ndisc/simple", test_simple); - g_test_add_func("/ndisc/everything-changed", test_everything); - g_test_add_func("/ndisc/preference-order", test_preference_order); - g_test_add_func("/ndisc/preference-changed", test_preference_changed); - g_test_add_func("/ndisc/dns-solicit-loop", test_dns_solicit_loop); - - return g_test_run(); -} diff --git a/src/nm-logging.c b/src/nm-logging.c deleted file mode 100644 index 11affbfb..00000000 --- a/src/nm-logging.c +++ /dev/null @@ -1,1036 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2006 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#include "nm-default.h" - -#include "nm-logging.h" - -#include <dlfcn.h> -#include <syslog.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <strings.h> - -#if SYSTEMD_JOURNAL - #define SD_JOURNAL_SUPPRESS_LOCATION - #include <systemd/sd-journal.h> -#endif - -#include "nm-glib-aux/nm-logging-base.h" -#include "nm-glib-aux/nm-time-utils.h" -#include "nm-errors.h" - -/*****************************************************************************/ - -/* Notes about thread-safety: - * - * NetworkManager generally is single-threaded and uses a (GLib) mainloop. - * However, nm-logging is in parts thread-safe. That means: - * - * - functions that configure logging (nm_logging_init(), nm_logging_setup()) and - * most other functions MUST be called only from the main-thread. These functions - * are expected to be called infrequently, so they may or may not use a mutex - * (but the overhead is negligible here). - * - * - functions that do the actual logging logging (nm_log(), nm_logging_enabled()) are - * thread-safe and may be used from multiple threads. - * - When called from the not-main-thread, @mt_require_locking must be set to %TRUE. - * In this case, a Mutex will be used for accessing the global state. - * - When called from the main-thread, they may optionally pass @mt_require_locking %FALSE. - * This avoids extra locking and is in particular interesting for nm_logging_enabled(), - * which is expected to be called frequently and from the main-thread. - * - * Note that the logging macros honor %NM_THREAD_SAFE_ON_MAIN_THREAD define, to automatically - * set @mt_require_locking. That means, by default %NM_THREAD_SAFE_ON_MAIN_THREAD is "1", - * and code that only runs on the main-thread (which is the majority), can get away - * without locking. - */ - -/*****************************************************************************/ - -G_STATIC_ASSERT(LOG_EMERG == 0); -G_STATIC_ASSERT(LOG_ALERT == 1); -G_STATIC_ASSERT(LOG_CRIT == 2); -G_STATIC_ASSERT(LOG_ERR == 3); -G_STATIC_ASSERT(LOG_WARNING == 4); -G_STATIC_ASSERT(LOG_NOTICE == 5); -G_STATIC_ASSERT(LOG_INFO == 6); -G_STATIC_ASSERT(LOG_DEBUG == 7); - -/* We have more then 32 logging domains. Assert that it compiles to a 64 bit sized enum */ -G_STATIC_ASSERT(sizeof(NMLogDomain) >= sizeof(guint64)); - -/* Combined domains */ -#define LOGD_ALL_STRING "ALL" -#define LOGD_DEFAULT_STRING "DEFAULT" -#define LOGD_DHCP_STRING "DHCP" -#define LOGD_IP_STRING "IP" - -/*****************************************************************************/ - -typedef enum { - LOG_BACKEND_GLIB, - LOG_BACKEND_SYSLOG, - LOG_BACKEND_JOURNAL, -} LogBackend; - -typedef struct { - NMLogDomain num; - const char *name; -} LogDesc; - -typedef struct { - char *logging_domains_to_string; -} GlobalMain; - -typedef struct { - NMLogLevel log_level; - bool uses_syslog : 1; - bool init_pre_done : 1; - bool init_done : 1; - bool debug_stderr : 1; - const char *prefix; - const char *syslog_identifier; - - /* before we setup syslog (during start), the backend defaults to GLIB, meaning: - * we use g_log() for all logging. At that point, the application is not yet supposed - * to do any logging and doing so indicates a bug. - * - * Afterwards, the backend is either SYSLOG or JOURNAL. From that point, also - * g_log() is redirected to this backend via a logging handler. */ - LogBackend log_backend; -} Global; - -/*****************************************************************************/ - -G_LOCK_DEFINE_STATIC(log); - -/* This data must only be accessed from the main-thread (and as - * such does not need any lock). */ -static GlobalMain gl_main = {}; - -static union { - /* a union with an immutable and a mutable alias for the Global. - * Since nm-logging must be thread-safe, we must take care at which - * places we only read value ("imm") and where we modify them ("mut"). */ - Global mut; - const Global imm; -} gl = { - .imm = - { - /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */ - .log_level = LOGL_INFO, - .log_backend = LOG_BACKEND_GLIB, - .syslog_identifier = "SYSLOG_IDENTIFIER=" G_LOG_DOMAIN, - .prefix = "", - }, -}; - -NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = { - /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); - * - * Note: LOGD_VPN_PLUGIN is special and must be disabled for - * DEBUG and TRACE levels. */ - [LOGL_INFO] = LOGD_DEFAULT, - [LOGL_WARN] = LOGD_DEFAULT, - [LOGL_ERR] = LOGD_DEFAULT, -}; - -/*****************************************************************************/ - -static const LogDesc domain_desc[] = { - {LOGD_PLATFORM, "PLATFORM"}, - {LOGD_RFKILL, "RFKILL"}, - {LOGD_ETHER, "ETHER"}, - {LOGD_WIFI, "WIFI"}, - {LOGD_BT, "BT"}, - {LOGD_MB, "MB"}, - {LOGD_DHCP4, "DHCP4"}, - {LOGD_DHCP6, "DHCP6"}, - {LOGD_PPP, "PPP"}, - {LOGD_WIFI_SCAN, "WIFI_SCAN"}, - {LOGD_IP4, "IP4"}, - {LOGD_IP6, "IP6"}, - {LOGD_AUTOIP4, "AUTOIP4"}, - {LOGD_DNS, "DNS"}, - {LOGD_VPN, "VPN"}, - {LOGD_SHARING, "SHARING"}, - {LOGD_SUPPLICANT, "SUPPLICANT"}, - {LOGD_AGENTS, "AGENTS"}, - {LOGD_SETTINGS, "SETTINGS"}, - {LOGD_SUSPEND, "SUSPEND"}, - {LOGD_CORE, "CORE"}, - {LOGD_DEVICE, "DEVICE"}, - {LOGD_OLPC, "OLPC"}, - {LOGD_INFINIBAND, "INFINIBAND"}, - {LOGD_FIREWALL, "FIREWALL"}, - {LOGD_ADSL, "ADSL"}, - {LOGD_BOND, "BOND"}, - {LOGD_VLAN, "VLAN"}, - {LOGD_BRIDGE, "BRIDGE"}, - {LOGD_DBUS_PROPS, "DBUS_PROPS"}, - {LOGD_TEAM, "TEAM"}, - {LOGD_CONCHECK, "CONCHECK"}, - {LOGD_DCB, "DCB"}, - {LOGD_DISPATCH, "DISPATCH"}, - {LOGD_AUDIT, "AUDIT"}, - {LOGD_SYSTEMD, "SYSTEMD"}, - {LOGD_VPN_PLUGIN, "VPN_PLUGIN"}, - {LOGD_PROXY, "PROXY"}, - {0}, -}; - -/*****************************************************************************/ - -static char *_domains_to_string(gboolean include_level_override, - NMLogLevel log_level, - const NMLogDomain log_state[static _LOGL_N_REAL]); - -/*****************************************************************************/ - -static gboolean -_syslog_identifier_valid_domain(const char *domain) -{ - char c; - - if (!domain || !domain[0]) - return FALSE; - - /* we pass the syslog identifier as format string. No funny stuff. */ - - for (; (c = domain[0]); domain++) { - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') - || NM_IN_SET(c, '-', '_')) - continue; - return FALSE; - } - return TRUE; -} - -static gboolean -_syslog_identifier_assert(const char *syslog_identifier) -{ - g_assert(syslog_identifier); - g_assert(g_str_has_prefix(syslog_identifier, "SYSLOG_IDENTIFIER=")); - g_assert(_syslog_identifier_valid_domain(&syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")])); - return TRUE; -} - -static const char * -syslog_identifier_domain(const char *syslog_identifier) -{ - nm_assert(_syslog_identifier_assert(syslog_identifier)); - return &syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")]; -} - -#if SYSTEMD_JOURNAL -static const char * -syslog_identifier_full(const char *syslog_identifier) -{ - nm_assert(_syslog_identifier_assert(syslog_identifier)); - return &syslog_identifier[0]; -} -#endif - -/*****************************************************************************/ - -static gboolean -match_log_level(const char *level, NMLogLevel *out_level, GError **error) -{ - if (_nm_log_parse_level(level, out_level)) - return TRUE; - - g_set_error(error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, - _("Unknown log level '%s'"), - level); - return FALSE; -} - -gboolean -nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error) -{ - GString * unrecognized = NULL; - NMLogDomain cur_log_state[_LOGL_N_REAL]; - NMLogDomain new_log_state[_LOGL_N_REAL]; - NMLogLevel cur_log_level; - NMLogLevel new_log_level; - gs_free const char **domains_v = NULL; - gsize i_d; - int i; - gboolean had_platform_debug; - gs_free char * domains_free = NULL; - - NM_ASSERT_ON_MAIN_THREAD(); - - g_return_val_if_fail(!bad_domains || !*bad_domains, FALSE); - g_return_val_if_fail(!error || !*error, FALSE); - - cur_log_level = gl.imm.log_level; - memcpy(cur_log_state, _nm_logging_enabled_state, sizeof(cur_log_state)); - - new_log_level = cur_log_level; - - if (!domains || !*domains) { - domains_free = _domains_to_string(FALSE, cur_log_level, cur_log_state); - domains = domains_free; - } - - for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) - new_log_state[i] = 0; - - if (level && *level) { - if (!match_log_level(level, &new_log_level, error)) - return FALSE; - if (new_log_level == _LOGL_KEEP) { - new_log_level = cur_log_level; - for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) - new_log_state[i] = cur_log_state[i]; - } - } - - domains_v = nm_utils_strsplit_set(domains, ", "); - for (i_d = 0; domains_v && domains_v[i_d]; i_d++) { - const char * s = domains_v[i_d]; - const char * p; - const LogDesc *diter; - NMLogLevel domain_log_level; - NMLogDomain bits; - - /* LOGD_VPN_PLUGIN is protected, that is, when setting ALL or DEFAULT, - * it does not enable the verbose levels DEBUG and TRACE, because that - * may expose sensitive data. */ - NMLogDomain protect = LOGD_NONE; - - p = strchr(s, ':'); - if (p) { - *((char *) p) = '\0'; - if (!match_log_level(p + 1, &domain_log_level, error)) - return FALSE; - } else - domain_log_level = new_log_level; - - bits = 0; - - if (domains_free) { - /* The caller didn't provide any domains to set (`nmcli general logging level DEBUG`). - * We reset all domains that were previously set, but we still want to protect - * VPN_PLUGIN domain. */ - protect = LOGD_VPN_PLUGIN; - } - - /* Check for combined domains */ - if (!g_ascii_strcasecmp(s, LOGD_ALL_STRING)) { - bits = LOGD_ALL; - protect = LOGD_VPN_PLUGIN; - } else if (!g_ascii_strcasecmp(s, LOGD_DEFAULT_STRING)) { - bits = LOGD_DEFAULT; - protect = LOGD_VPN_PLUGIN; - } else if (!g_ascii_strcasecmp(s, LOGD_DHCP_STRING)) - bits = LOGD_DHCP; - else if (!g_ascii_strcasecmp(s, LOGD_IP_STRING)) - bits = LOGD_IP; - - /* Check for compatibility domains */ - else if (!g_ascii_strcasecmp(s, "HW")) - bits = LOGD_PLATFORM; - else if (!g_ascii_strcasecmp(s, "WIMAX")) - continue; - - else { - for (diter = &domain_desc[0]; diter->name; diter++) { - if (!g_ascii_strcasecmp(diter->name, s)) { - bits = diter->num; - break; - } - } - - if (!bits) { - if (!bad_domains) { - g_set_error(error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, - _("Unknown log domain '%s'"), - s); - return FALSE; - } - - if (unrecognized) - g_string_append(unrecognized, ", "); - else - unrecognized = g_string_new(NULL); - g_string_append(unrecognized, s); - continue; - } - } - - if (domain_log_level == _LOGL_KEEP) { - for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) - new_log_state[i] = (new_log_state[i] & ~bits) | (cur_log_state[i] & bits); - } else { - for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) { - if (i < domain_log_level) - new_log_state[i] &= ~bits; - else { - new_log_state[i] |= bits; - if ((protect & bits) && i < LOGL_INFO) - new_log_state[i] &= ~protect; - } - } - } - } - - nm_clear_g_free(&gl_main.logging_domains_to_string); - - had_platform_debug = _nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM); - - G_LOCK(log); - - gl.mut.log_level = new_log_level; - for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) - _nm_logging_enabled_state[i] = new_log_state[i]; - - G_UNLOCK(log); - - if (had_platform_debug && !_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM)) { - /* when debug logging is enabled, platform will cache all access to - * sysctl. When the user disables debug-logging, we want to clear that - * cache right away. */ - _nm_logging_clear_platform_logging_cache(); - } - - if (unrecognized) - *bad_domains = g_string_free(unrecognized, FALSE); - - return TRUE; -} - -const char * -nm_logging_level_to_string(void) -{ - NM_ASSERT_ON_MAIN_THREAD(); - - return level_desc[gl.imm.log_level].name; -} - -const char * -nm_logging_all_levels_to_string(void) -{ - static GString *str; - - if (G_UNLIKELY(!str)) { - int i; - - str = g_string_new(NULL); - for (i = 0; i < G_N_ELEMENTS(level_desc); i++) { - if (str->len) - g_string_append_c(str, ','); - g_string_append(str, level_desc[i].name); - } - } - - return str->str; -} - -const char * -nm_logging_domains_to_string(void) -{ - NM_ASSERT_ON_MAIN_THREAD(); - - if (G_UNLIKELY(!gl_main.logging_domains_to_string)) { - gl_main.logging_domains_to_string = - _domains_to_string(TRUE, gl.imm.log_level, _nm_logging_enabled_state); - } - - return gl_main.logging_domains_to_string; -} - -static char * -_domains_to_string(gboolean include_level_override, - NMLogLevel log_level, - const NMLogDomain log_state[static _LOGL_N_REAL]) -{ - const LogDesc *diter; - GString * str; - int i; - - /* We don't just return g_strdup() the logging domains that were set during - * nm_logging_setup(), because we want to expand "DEFAULT" and "ALL". - */ - - str = g_string_sized_new(75); - for (diter = &domain_desc[0]; diter->name; diter++) { - /* If it's set for any lower level, it will also be set for LOGL_ERR */ - if (!(diter->num & log_state[LOGL_ERR])) - continue; - - if (str->len) - g_string_append_c(str, ','); - g_string_append(str, diter->name); - - if (!include_level_override) - continue; - - /* Check if it's logging at a lower level than the default. */ - for (i = 0; i < log_level; i++) { - if (diter->num & log_state[i]) { - g_string_append_printf(str, ":%s", level_desc[i].name); - break; - } - } - /* Check if it's logging at a higher level than the default. */ - if (!(diter->num & log_state[log_level])) { - for (i = log_level + 1; i < _LOGL_N_REAL; i++) { - if (diter->num & log_state[i]) { - g_string_append_printf(str, ":%s", level_desc[i].name); - break; - } - } - } - } - return g_string_free(str, FALSE); -} - -static char _all_logging_domains_to_str[273]; - -const char * -nm_logging_all_domains_to_string(void) -{ - static const char *volatile str = NULL; - const char *s; - -again: - s = g_atomic_pointer_get(&str); - if (G_UNLIKELY(!s)) { - static gsize once = 0; - const LogDesc *diter; - gsize buf_l; - char * buf_p; - - if (!g_once_init_enter(&once)) - goto again; - - buf_p = _all_logging_domains_to_str; - buf_l = sizeof(_all_logging_domains_to_str); - - nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_DEFAULT_STRING); - for (diter = &domain_desc[0]; diter->name; diter++) { - nm_utils_strbuf_append_c(&buf_p, &buf_l, ','); - nm_utils_strbuf_append_str(&buf_p, &buf_l, diter->name); - if (diter->num == LOGD_DHCP6) - nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_DHCP_STRING); - else if (diter->num == LOGD_IP6) - nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_IP_STRING); - } - nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_ALL_STRING); - - /* Did you modify the logging domains (or their names)? Adjust the size of - * _all_logging_domains_to_str buffer above to have the exact size. */ - nm_assert(strlen(_all_logging_domains_to_str) == sizeof(_all_logging_domains_to_str) - 1); - nm_assert(buf_l == 1); - - s = _all_logging_domains_to_str; - g_atomic_pointer_set(&str, s); - g_once_init_leave(&once, 1); - } - - return s; -} - -/** - * nm_logging_get_level: - * @domain: find the lowest enabled logging level for the - * given domain. If this is a set of multiple - * domains, the most verbose level will be returned. - * - * Returns: the lowest (most verbose) logging level for the - * give @domain, or %_LOGL_OFF if it is disabled. - **/ -NMLogLevel -nm_logging_get_level(NMLogDomain domain) -{ - NMLogLevel sl = _LOGL_OFF; - - G_STATIC_ASSERT(LOGL_TRACE == 0); - while (sl > LOGL_TRACE && _nm_logging_enabled_lockfree(sl - 1, domain)) - sl--; - return sl; -} - -gboolean -_nm_logging_enabled_locking(NMLogLevel level, NMLogDomain domain) -{ - gboolean v; - - G_LOCK(log); - v = _nm_logging_enabled_lockfree(level, domain); - G_UNLOCK(log); - return v; -} - -gboolean -_nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain) -{ - return nm_logging_enabled_mt(mt_require_locking, level, domain); -} - -#if SYSTEMD_JOURNAL -static void -_iovec_set(struct iovec *iov, const void *str, gsize len) -{ - iov->iov_base = (void *) str; - iov->iov_len = len; -} - -static void -_iovec_set_string(struct iovec *iov, const char *str) -{ - _iovec_set(iov, str, strlen(str)); -} - - #define _iovec_set_string_literal(iov, str) _iovec_set((iov), "" str "", NM_STRLEN(str)) - -_nm_printf(3, 4) static void _iovec_set_format(struct iovec *iov, - char ** iov_free, - const char * format, - ...) -{ - va_list ap; - char * str; - - va_start(ap, format); - str = g_strdup_vprintf(format, ap); - va_end(ap); - - _iovec_set_string(iov, str); - *iov_free = str; -} - - #define _iovec_set_format_a(iov, reserve_extra, format, ...) \ - G_STMT_START \ - { \ - const gsize _size = (reserve_extra) + (NM_STRLEN(format) + 3); \ - char *const _buf = g_alloca(_size); \ - int _len; \ - \ - G_STATIC_ASSERT_EXPR((reserve_extra) + (NM_STRLEN(format) + 3) <= 96); \ - \ - _len = g_snprintf(_buf, _size, "" format "", ##__VA_ARGS__); \ - \ - nm_assert(_len >= 0); \ - nm_assert(_len < _size); \ - nm_assert(_len == strlen(_buf)); \ - \ - _iovec_set((iov), _buf, _len); \ - } \ - G_STMT_END - - #define _iovec_set_format_str_a(iov, max_str_len, format, str_arg) \ - G_STMT_START \ - { \ - const char *_str_arg = (str_arg); \ - \ - nm_assert(_str_arg &&strlen(_str_arg) < (max_str_len)); \ - _iovec_set_format_a((iov), (max_str_len), format, str_arg); \ - } \ - G_STMT_END - -#endif - -void -_nm_log_impl(const char *file, - guint line, - const char *func, - gboolean mt_require_locking, - NMLogLevel level, - NMLogDomain domain, - int error, - const char *ifname, - const char *conn_uuid, - const char *fmt, - ...) -{ - va_list args; - char * msg; - GTimeVal tv; - int errsv; - const NMLogDomain *cur_log_state; - NMLogDomain cur_log_state_copy[_LOGL_N_REAL]; - Global g_copy; - const Global * g; - - if (G_UNLIKELY(mt_require_locking)) { - G_LOCK(log); - /* we evaluate logging-enabled under lock. There is still a race that - * we might log the message below *after* logging was disabled. That means, - * when disabling logging, we might still log messages. */ - if (!_nm_logging_enabled_lockfree(level, domain)) { - G_UNLOCK(log); - return; - } - g_copy = gl.imm; - memcpy(cur_log_state_copy, _nm_logging_enabled_state, sizeof(cur_log_state_copy)); - G_UNLOCK(log); - g = &g_copy; - cur_log_state = cur_log_state_copy; - } else { - NM_ASSERT_ON_MAIN_THREAD(); - if (!_nm_logging_enabled_lockfree(level, domain)) - return; - g = &gl.imm; - cur_log_state = _nm_logging_enabled_state; - } - - (void) cur_log_state; - - errsv = errno; - - /* Make sure that %m maps to the specified error */ - if (error != 0) { - if (error < 0) - error = -error; - errno = error; - } - - va_start(args, fmt); - msg = g_strdup_vprintf(fmt, args); - va_end(args); - -#define MESSAGE_FMT "%s%-7s [%ld.%04ld] %s" -#define MESSAGE_ARG(prefix, tv, msg) \ - prefix, level_desc[level].level_str, (tv).tv_sec, ((tv).tv_usec / 100), (msg) - - g_get_current_time(&tv); - - if (g->debug_stderr) - g_printerr(MESSAGE_FMT "\n", MESSAGE_ARG(g->prefix, tv, msg)); - - switch (g->log_backend) { -#if SYSTEMD_JOURNAL - case LOG_BACKEND_JOURNAL: - { - gint64 now, boottime; - struct iovec iov_data[15]; - struct iovec * iov = iov_data; - char * iov_free_data[5]; - char ** iov_free = iov_free_data; - const LogDesc *diter; - NMLogDomain dom_all; - char s_log_domains_buf[NM_STRLEN("NM_LOG_DOMAINS=") + sizeof(_all_logging_domains_to_str)]; - char *s_log_domains; - gsize l_log_domains; - - now = nm_utils_get_monotonic_timestamp_nsec(); - boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1); - - _iovec_set_format_a(iov++, 30, "PRIORITY=%d", level_desc[level].syslog_level); - _iovec_set_format(iov++, - iov_free++, - "MESSAGE=" MESSAGE_FMT, - MESSAGE_ARG(g->prefix, tv, msg)); - _iovec_set_string(iov++, syslog_identifier_full(g->syslog_identifier)); - _iovec_set_format_a(iov++, 30, "SYSLOG_PID=%ld", (long) getpid()); - - dom_all = domain; - s_log_domains = s_log_domains_buf; - l_log_domains = sizeof(s_log_domains_buf); - - nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS="); - for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) { - if (!NM_FLAGS_ANY(dom_all, diter->num)) - continue; - if (dom_all != domain) - nm_utils_strbuf_append_c(&s_log_domains, &l_log_domains, ','); - nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, diter->name); - dom_all &= ~diter->num; - } - nm_assert(l_log_domains > 0); - _iovec_set(iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf); - - G_STATIC_ASSERT_EXPR(LOG_FAC(LOG_DAEMON) == 3); - _iovec_set_string_literal(iov++, "SYSLOG_FACILITY=3"); - _iovec_set_format_str_a(iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name); - if (func) - _iovec_set_format(iov++, iov_free++, "CODE_FUNC=%s", func); - _iovec_set_format(iov++, iov_free++, "CODE_FILE=%s", file ?: ""); - _iovec_set_format_a(iov++, 20, "CODE_LINE=%u", line); - _iovec_set_format_a(iov++, - 60, - "TIMESTAMP_MONOTONIC=%lld.%06lld", - (long long) (now / NM_UTILS_NSEC_PER_SEC), - (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000)); - _iovec_set_format_a(iov++, - 60, - "TIMESTAMP_BOOTTIME=%lld.%06lld", - (long long) (boottime / NM_UTILS_NSEC_PER_SEC), - (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000)); - if (error != 0) - _iovec_set_format_a(iov++, 30, "ERRNO=%d", error); - if (ifname) - _iovec_set_format(iov++, iov_free++, "NM_DEVICE=%s", ifname); - if (conn_uuid) - _iovec_set_format(iov++, iov_free++, "NM_CONNECTION=%s", conn_uuid); - - nm_assert(iov <= &iov_data[G_N_ELEMENTS(iov_data)]); - nm_assert(iov_free <= &iov_free_data[G_N_ELEMENTS(iov_free_data)]); - - sd_journal_sendv(iov_data, iov - iov_data); - - for (; --iov_free >= iov_free_data;) - g_free(*iov_free); - } break; -#endif - case LOG_BACKEND_SYSLOG: - syslog(level_desc[level].syslog_level, MESSAGE_FMT, MESSAGE_ARG(g->prefix, tv, msg)); - break; - default: - g_log(syslog_identifier_domain(g->syslog_identifier), - level_desc[level].g_log_level, - MESSAGE_FMT, - MESSAGE_ARG(g->prefix, tv, msg)); - break; - } - - g_free(msg); - - errno = errsv; -} - -/*****************************************************************************/ - -void -_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, - gint64 offset_sec, - gboolean is_boottime) -{ - NM_ASSERT_ON_MAIN_THREAD(); - - if (_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_CORE)) { - time_t now = time(NULL); - struct tm tm; - char s[255]; - - strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime_r(&now, &tm)); - nm_log_dbg(LOGD_CORE, - "monotonic timestamp started counting 1.%09ld seconds ago with " - "an offset of %lld.0 seconds to %s (local time is %s)", - tp->tv_nsec, - (long long) -offset_sec, - is_boottime ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC", - s); - } -} - -/*****************************************************************************/ - -static void -nm_log_handler(const char *log_domain, GLogLevelFlags level, const char *message, gpointer ignored) -{ - int syslog_priority; - - switch (level & G_LOG_LEVEL_MASK) { - case G_LOG_LEVEL_ERROR: - syslog_priority = LOG_CRIT; - break; - case G_LOG_LEVEL_CRITICAL: - syslog_priority = LOG_ERR; - break; - case G_LOG_LEVEL_WARNING: - syslog_priority = LOG_WARNING; - break; - case G_LOG_LEVEL_MESSAGE: - syslog_priority = LOG_NOTICE; - break; - case G_LOG_LEVEL_DEBUG: - syslog_priority = LOG_DEBUG; - break; - case G_LOG_LEVEL_INFO: - default: - syslog_priority = LOG_INFO; - break; - } - - /* we don't need any locking here. The glib log handler gets only registered - * once during nm_logging_init() and the global data is not modified afterwards. */ - nm_assert(gl.imm.init_done); - - if (gl.imm.debug_stderr) - g_printerr("%s%s\n", gl.imm.prefix, message ?: ""); - - switch (gl.imm.log_backend) { -#if SYSTEMD_JOURNAL - case LOG_BACKEND_JOURNAL: - { - gint64 now, boottime; - - now = nm_utils_get_monotonic_timestamp_nsec(); - boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1); - - sd_journal_send("PRIORITY=%d", - syslog_priority, - "MESSAGE=%s%s", - gl.imm.prefix, - message ?: "", - syslog_identifier_full(gl.imm.syslog_identifier), - "SYSLOG_PID=%ld", - (long) getpid(), - "SYSLOG_FACILITY=3", - "GLIB_DOMAIN=%s", - log_domain ?: "", - "GLIB_LEVEL=%d", - (int) (level & G_LOG_LEVEL_MASK), - "TIMESTAMP_MONOTONIC=%lld.%06lld", - (long long) (now / NM_UTILS_NSEC_PER_SEC), - (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000), - "TIMESTAMP_BOOTTIME=%lld.%06lld", - (long long) (boottime / NM_UTILS_NSEC_PER_SEC), - (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000), - NULL); - } break; -#endif - default: - syslog(syslog_priority, "%s%s", gl.imm.prefix, message ?: ""); - break; - } -} - -gboolean -nm_logging_syslog_enabled(void) -{ - NM_ASSERT_ON_MAIN_THREAD(); - - return gl.imm.uses_syslog; -} - -void -nm_logging_init_pre(const char *syslog_identifier, char *prefix_take) -{ - /* this function may be called zero or one times, and only - * - on the main thread - * - not after nm_logging_init(). */ - - NM_ASSERT_ON_MAIN_THREAD(); - - if (gl.imm.init_pre_done) - g_return_if_reached(); - - if (gl.imm.init_done) - g_return_if_reached(); - - if (!_syslog_identifier_valid_domain(syslog_identifier)) - g_return_if_reached(); - - if (!prefix_take || !prefix_take[0]) - g_return_if_reached(); - - G_LOCK(log); - - gl.mut.init_pre_done = TRUE; - - gl.mut.syslog_identifier = g_strdup_printf("SYSLOG_IDENTIFIER=%s", syslog_identifier); - nm_assert(_syslog_identifier_assert(gl.imm.syslog_identifier)); - - /* we pass the allocated string on and never free it. */ - gl.mut.prefix = prefix_take; - - G_UNLOCK(log); -} - -void -nm_logging_init(const char *logging_backend, gboolean debug) -{ - gboolean fetch_monotonic_timestamp = FALSE; - gboolean obsolete_debug_backend = FALSE; - LogBackend x_log_backend; - - /* this function may be called zero or one times, and only on the - * main thread. */ - - NM_ASSERT_ON_MAIN_THREAD(); - - nm_assert(NM_IN_STRSET("" NM_CONFIG_DEFAULT_LOGGING_BACKEND, - NM_LOG_CONFIG_BACKEND_JOURNAL, - NM_LOG_CONFIG_BACKEND_SYSLOG)); - - if (gl.imm.init_done) - g_return_if_reached(); - - if (!logging_backend) - logging_backend = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND; - - if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_DEBUG)) { - /* "debug" was wrongly documented as a valid logging backend. It makes no sense however, - * because printing to stderr only makes sense when not demonizing. Whether to daemonize - * is only controlled via command line arguments (--no-daemon, --debug) and not via the - * logging backend from configuration. - * - * Fall back to the default. */ - logging_backend = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND; - obsolete_debug_backend = TRUE; - } - - G_LOCK(log); - -#if SYSTEMD_JOURNAL - if (!nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) { - x_log_backend = LOG_BACKEND_JOURNAL; - - /* We only log the monotonic-timestamp with structured logging (journal). - * Only in this case, fetch the timestamp. */ - fetch_monotonic_timestamp = TRUE; - } else -#endif - { - x_log_backend = LOG_BACKEND_SYSLOG; - openlog(syslog_identifier_domain(gl.imm.syslog_identifier), LOG_PID, LOG_DAEMON); - } - - gl.mut.init_done = TRUE; - gl.mut.log_backend = x_log_backend; - gl.mut.uses_syslog = TRUE; - gl.mut.debug_stderr = debug; - - g_log_set_handler(syslog_identifier_domain(gl.imm.syslog_identifier), - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION, - nm_log_handler, - NULL); - - G_UNLOCK(log); - - if (fetch_monotonic_timestamp) { - /* ensure we read a monotonic timestamp. Reading the timestamp the first - * time causes a logging message. We don't want to do that during _nm_log_impl. */ - nm_utils_get_monotonic_timestamp_nsec(); - } - - if (obsolete_debug_backend) - nm_log_dbg(LOGD_CORE, - "config: ignore deprecated logging backend 'debug', fallback to '%s'", - logging_backend); - - if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) { - /* good */ - } else if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_JOURNAL)) { -#if !SYSTEMD_JOURNAL - nm_log_warn(LOGD_CORE, - "config: logging backend 'journal' is not available, fallback to 'syslog'"); -#endif - } else { - nm_log_warn(LOGD_CORE, - "config: invalid logging backend '%s', fallback to '%s'", - logging_backend, -#if SYSTEMD_JOURNAL - NM_LOG_CONFIG_BACKEND_JOURNAL -#else - NM_LOG_CONFIG_BACKEND_SYSLOG -#endif - ); - } -} diff --git a/src/nm-logging.h b/src/nm-logging.h deleted file mode 100644 index b2251c92..00000000 --- a/src/nm-logging.h +++ /dev/null @@ -1,201 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2006 - 2012 Red Hat, Inc. - * Copyright (C) 2006 - 2008 Novell, Inc. - */ - -#ifndef __NETWORKMANAGER_LOGGING_H__ -#define __NETWORKMANAGER_LOGGING_H__ - -#ifdef __NM_TEST_UTILS_H__ - #error nm-test-utils.h must be included as last header -#endif - -#include "nm-glib-aux/nm-logging-fwd.h" - -#define NM_LOG_CONFIG_BACKEND_DEBUG "debug" -#define NM_LOG_CONFIG_BACKEND_SYSLOG "syslog" -#define NM_LOG_CONFIG_BACKEND_JOURNAL "journal" - -static inline NMLogDomain -LOGD_IP_from_af(int addr_family) -{ - switch (addr_family) { - case AF_INET: - return LOGD_IP4; - case AF_INET6: - return LOGD_IP6; - } - g_return_val_if_reached(LOGD_NONE); -} - -#define nm_log_err(domain, ...) nm_log(LOGL_ERR, (domain), NULL, NULL, __VA_ARGS__) -#define nm_log_warn(domain, ...) nm_log(LOGL_WARN, (domain), NULL, NULL, __VA_ARGS__) -#define nm_log_info(domain, ...) nm_log(LOGL_INFO, (domain), NULL, NULL, __VA_ARGS__) -#define nm_log_dbg(domain, ...) nm_log(LOGL_DEBUG, (domain), NULL, NULL, __VA_ARGS__) -#define nm_log_trace(domain, ...) nm_log(LOGL_TRACE, (domain), NULL, NULL, __VA_ARGS__) - -//#define _NM_LOG_FUNC G_STRFUNC -#define _NM_LOG_FUNC NULL - -/* A wrapper for the _nm_log_impl() function that adds call site information. - * Contrary to nm_log(), it unconditionally calls the function without - * checking whether logging for the given level and domain is enabled. */ -#define _nm_log_mt(mt_require_locking, level, domain, error, ifname, con_uuid, ...) \ - G_STMT_START \ - { \ - _nm_log_impl(__FILE__, \ - __LINE__, \ - _NM_LOG_FUNC, \ - (mt_require_locking), \ - (level), \ - (domain), \ - (error), \ - (ifname), \ - (con_uuid), \ - ""__VA_ARGS__); \ - } \ - G_STMT_END - -#define _nm_log(level, domain, error, ifname, con_uuid, ...) \ - _nm_log_mt(!(NM_THREAD_SAFE_ON_MAIN_THREAD), \ - level, \ - domain, \ - error, \ - ifname, \ - con_uuid, \ - __VA_ARGS__) - -/* nm_log() only evaluates its argument list after checking - * whether logging for the given level/domain is enabled. */ -#define nm_log(level, domain, ifname, con_uuid, ...) \ - G_STMT_START \ - { \ - if (nm_logging_enabled((level), (domain))) { \ - _nm_log(level, domain, 0, ifname, con_uuid, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - -#define _nm_log_ptr(level, domain, ifname, con_uuid, self, prefix, ...) \ - nm_log((level), \ - (domain), \ - (ifname), \ - (con_uuid), \ - "%s[" NM_HASH_OBFUSCATE_PTR_FMT "] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (prefix) ?: "", \ - NM_HASH_OBFUSCATE_PTR(self) _NM_UTILS_MACRO_REST(__VA_ARGS__)) - -static inline gboolean -_nm_log_ptr_is_debug(NMLogLevel level) -{ - return level <= LOGL_DEBUG; -} - -/* log a message for an object (with providing a generic @self pointer) */ -#define nm_log_ptr(level, domain, ifname, con_uuid, self, prefix, ...) \ - G_STMT_START \ - { \ - if (_nm_log_ptr_is_debug(level)) { \ - _nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), (prefix), __VA_ARGS__); \ - } else { \ - const char *__prefix = (prefix); \ - \ - nm_log((level), \ - (domain), \ - (ifname), \ - (con_uuid), \ - "%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - __prefix ?: "", \ - __prefix ? " " : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ - G_STMT_END - -#define _nm_log_obj(level, domain, ifname, con_uuid, self, prefix, ...) \ - _nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), prefix, __VA_ARGS__) - -/* log a message for an object (with providing a @self pointer to a GObject). - * Contrary to nm_log_ptr(), @self must be a GObject type (or %NULL). - * As of now, nm_log_obj() is identical to nm_log_ptr(), but we might change that */ -#define nm_log_obj(level, domain, ifname, con_uuid, self, prefix, ...) \ - nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), prefix, __VA_ARGS__) - -const char *nm_logging_level_to_string(void); -const char *nm_logging_domains_to_string(void); - -/*****************************************************************************/ - -extern NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL]; - -static inline gboolean -_nm_logging_enabled_lockfree(NMLogLevel level, NMLogDomain domain) -{ - nm_assert(((guint) level) < G_N_ELEMENTS(_nm_logging_enabled_state)); - return (((guint) level) < G_N_ELEMENTS(_nm_logging_enabled_state)) - && !!(_nm_logging_enabled_state[level] & domain); -} - -gboolean _nm_logging_enabled_locking(NMLogLevel level, NMLogDomain domain); - -static inline gboolean -nm_logging_enabled_mt(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain) -{ - if (mt_require_locking) - return _nm_logging_enabled_locking(level, domain); - - NM_ASSERT_ON_MAIN_THREAD(); - return _nm_logging_enabled_lockfree(level, domain); -} - -#define nm_logging_enabled(level, domain) \ - nm_logging_enabled_mt(!(NM_THREAD_SAFE_ON_MAIN_THREAD), level, domain) - -/*****************************************************************************/ - -NMLogLevel nm_logging_get_level(NMLogDomain domain); - -const char *nm_logging_all_levels_to_string(void); -const char *nm_logging_all_domains_to_string(void); - -gboolean -nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error); - -void nm_logging_init_pre(const char *syslog_identifier, char *prefix_take); - -void nm_logging_init(const char *logging_backend, gboolean debug); - -gboolean nm_logging_syslog_enabled(void); - -/*****************************************************************************/ - -#define __NMLOG_DEFAULT(level, domain, prefix, ...) \ - G_STMT_START \ - { \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (prefix) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -#define __NMLOG_DEFAULT_WITH_ADDR(level, domain, prefix, ...) \ - G_STMT_START \ - { \ - nm_log((level), \ - (domain), \ - NULL, \ - NULL, \ - "%s[" NM_HASH_OBFUSCATE_PTR_FMT "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (prefix), \ - NM_HASH_OBFUSCATE_PTR(self) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -extern void _nm_logging_clear_platform_logging_cache(void); - -#endif /* __NETWORKMANAGER_LOGGING_H__ */ diff --git a/src/platform/nm-netlink.c b/src/platform/nm-netlink.c deleted file mode 100644 index 965a73bc..00000000 --- a/src/platform/nm-netlink.c +++ /dev/null @@ -1,1518 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-netlink.h" - -#include <unistd.h> -#include <fcntl.h> - -/*****************************************************************************/ - -#ifndef SOL_NETLINK - #define SOL_NETLINK 270 -#endif - -/*****************************************************************************/ - -#define NL_SOCK_PASSCRED (1 << 1) -#define NL_MSG_PEEK (1 << 3) -#define NL_MSG_PEEK_EXPLICIT (1 << 4) -#define NL_NO_AUTO_ACK (1 << 5) - -#ifndef NETLINK_EXT_ACK - #define NETLINK_EXT_ACK 11 -#endif - -struct nl_msg { - int nm_protocol; - struct sockaddr_nl nm_src; - struct sockaddr_nl nm_dst; - struct ucred nm_creds; - struct nlmsghdr * nm_nlh; - size_t nm_size; - bool nm_creds_has : 1; -}; - -struct nl_sock { - struct sockaddr_nl s_local; - struct sockaddr_nl s_peer; - int s_fd; - int s_proto; - unsigned int s_seq_next; - unsigned int s_seq_expect; - int s_flags; - size_t s_bufsize; -}; - -/*****************************************************************************/ - -NM_UTILS_ENUM2STR_DEFINE(nl_nlmsgtype2str, - int, - NM_UTILS_ENUM2STR(NLMSG_NOOP, "NOOP"), - NM_UTILS_ENUM2STR(NLMSG_ERROR, "ERROR"), - NM_UTILS_ENUM2STR(NLMSG_DONE, "DONE"), - NM_UTILS_ENUM2STR(NLMSG_OVERRUN, "OVERRUN"), ); - -NM_UTILS_FLAGS2STR_DEFINE(nl_nlmsg_flags2str, - int, - NM_UTILS_FLAGS2STR(NLM_F_REQUEST, "REQUEST"), - NM_UTILS_FLAGS2STR(NLM_F_MULTI, "MULTI"), - NM_UTILS_FLAGS2STR(NLM_F_ACK, "ACK"), - NM_UTILS_FLAGS2STR(NLM_F_ECHO, "ECHO"), - NM_UTILS_FLAGS2STR(NLM_F_ROOT, "ROOT"), - NM_UTILS_FLAGS2STR(NLM_F_MATCH, "MATCH"), - NM_UTILS_FLAGS2STR(NLM_F_ATOMIC, "ATOMIC"), - NM_UTILS_FLAGS2STR(NLM_F_REPLACE, "REPLACE"), - NM_UTILS_FLAGS2STR(NLM_F_EXCL, "EXCL"), - NM_UTILS_FLAGS2STR(NLM_F_CREATE, "CREATE"), - NM_UTILS_FLAGS2STR(NLM_F_APPEND, "APPEND"), ); - -/*****************************************************************************/ - -const char * -nl_nlmsghdr_to_str(const struct nlmsghdr *hdr, char *buf, gsize len) -{ - const char *b; - const char *s; - guint flags, flags_before; - const char *prefix; - - if (!nm_utils_to_string_buffer_init_null(hdr, &buf, &len)) - return buf; - - b = buf; - - switch (hdr->nlmsg_type) { - case RTM_GETLINK: - s = "RTM_GETLINK"; - break; - case RTM_NEWLINK: - s = "RTM_NEWLINK"; - break; - case RTM_DELLINK: - s = "RTM_DELLINK"; - break; - case RTM_SETLINK: - s = "RTM_SETLINK"; - break; - case RTM_GETADDR: - s = "RTM_GETADDR"; - break; - case RTM_NEWADDR: - s = "RTM_NEWADDR"; - break; - case RTM_DELADDR: - s = "RTM_DELADDR"; - break; - case RTM_GETROUTE: - s = "RTM_GETROUTE"; - break; - case RTM_NEWROUTE: - s = "RTM_NEWROUTE"; - break; - case RTM_DELROUTE: - s = "RTM_DELROUTE"; - break; - case RTM_GETRULE: - s = "RTM_GETRULE"; - break; - case RTM_NEWRULE: - s = "RTM_NEWRULE"; - break; - case RTM_DELRULE: - s = "RTM_DELRULE"; - break; - case RTM_GETQDISC: - s = "RTM_GETQDISC"; - break; - case RTM_NEWQDISC: - s = "RTM_NEWQDISC"; - break; - case RTM_DELQDISC: - s = "RTM_DELQDISC"; - break; - case RTM_GETTFILTER: - s = "RTM_GETTFILTER"; - break; - case RTM_NEWTFILTER: - s = "RTM_NEWTFILTER"; - break; - case RTM_DELTFILTER: - s = "RTM_DELTFILTER"; - break; - case NLMSG_NOOP: - s = "NLMSG_NOOP"; - break; - case NLMSG_ERROR: - s = "NLMSG_ERROR"; - break; - case NLMSG_DONE: - s = "NLMSG_DONE"; - break; - case NLMSG_OVERRUN: - s = "NLMSG_OVERRUN"; - break; - default: - s = NULL; - break; - } - - if (s) - nm_utils_strbuf_append_str(&buf, &len, s); - else - nm_utils_strbuf_append(&buf, &len, "(%u)", (unsigned) hdr->nlmsg_type); - - flags = hdr->nlmsg_flags; - - if (!flags) { - nm_utils_strbuf_append_str(&buf, &len, ", flags 0"); - goto flags_done; - } - -#define _F(f, n) \ - G_STMT_START \ - { \ - if (NM_FLAGS_ALL(flags, f)) { \ - flags &= ~(f); \ - nm_utils_strbuf_append(&buf, &len, "%s%s", prefix, n); \ - if (!flags) \ - goto flags_done; \ - prefix = ","; \ - } \ - } \ - G_STMT_END - - prefix = ", flags "; - flags_before = flags; - _F(NLM_F_REQUEST, "request"); - _F(NLM_F_MULTI, "multi"); - _F(NLM_F_ACK, "ack"); - _F(NLM_F_ECHO, "echo"); - _F(NLM_F_DUMP_INTR, "dump_intr"); - _F(0x20 /*NLM_F_DUMP_FILTERED*/, "dump_filtered"); - - if (flags_before != flags) - prefix = ";"; - - switch (hdr->nlmsg_type) { - case RTM_NEWLINK: - case RTM_NEWADDR: - case RTM_NEWROUTE: - case RTM_NEWQDISC: - case RTM_NEWTFILTER: - _F(NLM_F_REPLACE, "replace"); - _F(NLM_F_EXCL, "excl"); - _F(NLM_F_CREATE, "create"); - _F(NLM_F_APPEND, "append"); - break; - case RTM_GETLINK: - case RTM_GETADDR: - case RTM_GETROUTE: - case RTM_DELQDISC: - case RTM_DELTFILTER: - _F(NLM_F_DUMP, "dump"); - _F(NLM_F_ROOT, "root"); - _F(NLM_F_MATCH, "match"); - _F(NLM_F_ATOMIC, "atomic"); - break; - } - -#undef _F - - if (flags_before != flags) - prefix = ";"; - nm_utils_strbuf_append(&buf, &len, "%s0x%04x", prefix, flags); - -flags_done: - - nm_utils_strbuf_append(&buf, &len, ", seq %u", (unsigned) hdr->nlmsg_seq); - - return b; -} - -/*****************************************************************************/ - -struct nlmsghdr * -nlmsg_hdr(struct nl_msg *n) -{ - return n->nm_nlh; -} - -void * -nlmsg_reserve(struct nl_msg *n, size_t len, int pad) -{ - char * buf = (char *) n->nm_nlh; - size_t nlmsg_len = n->nm_nlh->nlmsg_len; - size_t tlen; - - nm_assert(pad >= 0); - - if (len > n->nm_size) - return NULL; - - tlen = pad ? ((len + (pad - 1)) & ~(pad - 1)) : len; - - if ((tlen + nlmsg_len) > n->nm_size) - return NULL; - - buf += nlmsg_len; - n->nm_nlh->nlmsg_len += tlen; - - if (tlen > len) - memset(buf + len, 0, tlen - len); - - return buf; -} - -/*****************************************************************************/ - -struct nlattr * -nla_reserve(struct nl_msg *msg, int attrtype, int attrlen) -{ - struct nlattr *nla; - int tlen; - - if (attrlen < 0) - return NULL; - - tlen = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + nla_total_size(attrlen); - - if (tlen > msg->nm_size) - return NULL; - - nla = (struct nlattr *) nlmsg_tail(msg->nm_nlh); - nla->nla_type = attrtype; - nla->nla_len = nla_attr_size(attrlen); - - if (attrlen) - memset((unsigned char *) nla + nla->nla_len, 0, nla_padlen(attrlen)); - msg->nm_nlh->nlmsg_len = tlen; - - return nla; -} - -/*****************************************************************************/ - -struct nl_msg * -nlmsg_alloc_size(size_t len) -{ - struct nl_msg *nm; - - if (len < sizeof(struct nlmsghdr)) - len = sizeof(struct nlmsghdr); - - nm = g_slice_new(struct nl_msg); - *nm = (struct nl_msg){ - .nm_protocol = -1, - .nm_size = len, - .nm_nlh = g_malloc0(len), - }; - nm->nm_nlh->nlmsg_len = nlmsg_total_size(0); - return nm; -} - -/** - * Allocate a new netlink message with the default maximum payload size. - * - * Allocates a new netlink message without any further payload. The - * maximum payload size defaults to PAGESIZE or as otherwise specified - * with nlmsg_set_default_size(). - * - * @return Newly allocated netlink message or NULL. - */ -struct nl_msg * -nlmsg_alloc(void) -{ - return nlmsg_alloc_size(nm_utils_getpagesize()); -} - -struct nl_msg * -nlmsg_alloc_convert(struct nlmsghdr *hdr) -{ - struct nl_msg *nm; - - nm = nlmsg_alloc_size(NLMSG_ALIGN(hdr->nlmsg_len)); - memcpy(nm->nm_nlh, hdr, hdr->nlmsg_len); - return nm; -} - -struct nl_msg * -nlmsg_alloc_simple(int nlmsgtype, int flags) -{ - struct nl_msg *nm; - struct nlmsghdr *new; - - nm = nlmsg_alloc(); - new = nm->nm_nlh; - new->nlmsg_type = nlmsgtype; - new->nlmsg_flags = flags; - return nm; -} - -void -nlmsg_free(struct nl_msg *msg) -{ - if (!msg) - return; - - g_free(msg->nm_nlh); - g_slice_free(struct nl_msg, msg); -} - -/*****************************************************************************/ - -int -nlmsg_append(struct nl_msg *n, const void *data, size_t len, int pad) -{ - void *tmp; - - nm_assert(n); - nm_assert(data); - nm_assert(len > 0); - nm_assert(pad >= 0); - - tmp = nlmsg_reserve(n, len, pad); - if (tmp == NULL) - return -ENOMEM; - - memcpy(tmp, data, len); - return 0; -} - -/*****************************************************************************/ - -int -nlmsg_parse(struct nlmsghdr * nlh, - int hdrlen, - struct nlattr * tb[], - int maxtype, - const struct nla_policy *policy) -{ - if (!nlmsg_valid_hdr(nlh, hdrlen)) - return -NME_NL_MSG_TOOSHORT; - - return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), policy); -} - -struct nlmsghdr * -nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags) -{ - struct nlmsghdr *nlh; - - if (n->nm_nlh->nlmsg_len < NLMSG_HDRLEN) - g_return_val_if_reached(NULL); - - nlh = (struct nlmsghdr *) n->nm_nlh; - nlh->nlmsg_type = type; - nlh->nlmsg_flags = flags; - nlh->nlmsg_pid = pid; - nlh->nlmsg_seq = seq; - - if (payload > 0 && nlmsg_reserve(n, payload, NLMSG_ALIGNTO) == NULL) - return NULL; - - return nlh; -} - -size_t -nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize) -{ - const char *src; - size_t srclen; - size_t len; - - /* - Always writes @dstsize bytes to @dst - * - Copies the first non-NUL characters to @dst. - * Any characters after the first NUL bytes in @nla are ignored. - * - If the string @nla is longer than @dstsize, the string - * gets truncated. @dst will always be NUL terminated. */ - - if (G_UNLIKELY(dstsize <= 1)) { - if (dstsize == 1) - dst[0] = '\0'; - if (nla && (srclen = nla_len(nla)) > 0) - return strnlen(nla_data(nla), srclen); - return 0; - } - - nm_assert(dst); - - if (nla) { - srclen = nla_len(nla); - if (srclen > 0) { - src = nla_data(nla); - srclen = strnlen(src, srclen); - if (srclen > 0) { - len = NM_MIN(dstsize - 1, srclen); - memcpy(dst, src, len); - memset(&dst[len], 0, dstsize - len); - return srclen; - } - } - } - - memset(dst, 0, dstsize); - return 0; -} - -size_t -nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize) -{ - size_t len; - int srclen; - - if (!nla) - return 0; - - srclen = nla_len(nla); - - if (srclen <= 0) { - nm_assert(srclen == 0); - return 0; - } - - len = NM_MIN((size_t) srclen, dstsize); - if (len > 0) { - /* there is a crucial difference between nla_strlcpy() and nla_memcpy(). - * The former always write @dstsize bytes (akin to strncpy()), here, we only - * write the bytes that we actually have (leaving the remainder undefined). */ - memcpy(dst, nla_data(nla), len); - } - - return srclen; -} - -int -nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) -{ - struct nlattr *nla; - - nla = nla_reserve(msg, attrtype, datalen); - if (!nla) { - if (datalen < 0) - g_return_val_if_reached(-NME_BUG); - - return -ENOMEM; - } - - if (datalen > 0) - memcpy(nla_data(nla), data, datalen); - - return 0; -} - -struct nlattr * -nla_find(const struct nlattr *head, int len, int attrtype) -{ - const struct nlattr *nla; - int rem; - - nla_for_each_attr (nla, head, len, rem) { - if (nla_type(nla) == attrtype) - return (struct nlattr *) nla; - } - - return NULL; -} - -void -nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr) -{ - ssize_t len; - - len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) attr; - if (len < 0) - g_return_if_reached(); - else if (len > 0) { - msg->nm_nlh->nlmsg_len -= len; - memset(nlmsg_tail(msg->nm_nlh), 0, len); - } -} - -struct nlattr * -nla_nest_start(struct nl_msg *msg, int attrtype) -{ - struct nlattr *start = (struct nlattr *) nlmsg_tail(msg->nm_nlh); - - if (nla_put(msg, NLA_F_NESTED | attrtype, 0, NULL) < 0) - return NULL; - - return start; -} - -static int -_nest_end(struct nl_msg *msg, struct nlattr *start, int keep_empty) -{ - size_t pad, len; - - len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) start; - - if (len > USHRT_MAX || (!keep_empty && len == NLA_HDRLEN)) { - /* - * Max nlattr size exceeded or empty nested attribute, trim the - * attribute header again - */ - nla_nest_cancel(msg, start); - - /* Return error only if nlattr size was exceeded */ - return (len == NLA_HDRLEN) ? 0 : -NME_NL_ATTRSIZE; - } - - start->nla_len = len; - - pad = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) - msg->nm_nlh->nlmsg_len; - if (pad > 0) { - /* - * Data inside attribute does not end at a alignment boundary. - * Pad accordingly and account for the additional space in - * the message. nlmsg_reserve() may never fail in this situation, - * the allocate message buffer must be a multiple of NLMSG_ALIGNTO. - */ - if (!nlmsg_reserve(msg, pad, 0)) - g_return_val_if_reached(-NME_BUG); - } - - return 0; -} - -int -nla_nest_end(struct nl_msg *msg, struct nlattr *start) -{ - return _nest_end(msg, start, 0); -} - -static const uint16_t nla_attr_minlen[NLA_TYPE_MAX + 1] = { - [NLA_U8] = sizeof(uint8_t), - [NLA_U16] = sizeof(uint16_t), - [NLA_U32] = sizeof(uint32_t), - [NLA_U64] = sizeof(uint64_t), - [NLA_STRING] = 1, - [NLA_FLAG] = 0, -}; - -static int -validate_nla(const struct nlattr *nla, int maxtype, const struct nla_policy *policy) -{ - const struct nla_policy *pt; - unsigned int minlen = 0; - int type = nla_type(nla); - - if (type < 0 || type > maxtype) - return 0; - - pt = &policy[type]; - - if (pt->type > NLA_TYPE_MAX) - g_return_val_if_reached(-NME_BUG); - - if (pt->minlen) - minlen = pt->minlen; - else if (pt->type != NLA_UNSPEC) - minlen = nla_attr_minlen[pt->type]; - - if (nla_len(nla) < minlen) - return -NME_UNSPEC; - - if (pt->maxlen && nla_len(nla) > pt->maxlen) - return -NME_UNSPEC; - - if (pt->type == NLA_STRING) { - const char *data; - - nm_assert(minlen > 0); - - data = nla_data(nla); - if (data[nla_len(nla) - 1] != '\0') - return -NME_UNSPEC; - } - - return 0; -} - -int -nla_parse(struct nlattr * tb[], - int maxtype, - struct nlattr * head, - int len, - const struct nla_policy *policy) -{ - struct nlattr *nla; - int rem, nmerr; - - memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); - - nla_for_each_attr (nla, head, len, rem) { - int type = nla_type(nla); - - if (type > maxtype) - continue; - - if (policy) { - nmerr = validate_nla(nla, maxtype, policy); - if (nmerr < 0) - return nmerr; - } - - tb[type] = nla; - } - - return 0; -} - -/*****************************************************************************/ - -int -nlmsg_get_proto(struct nl_msg *msg) -{ - return msg->nm_protocol; -} - -void -nlmsg_set_proto(struct nl_msg *msg, int protocol) -{ - msg->nm_protocol = protocol; -} - -void -nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr) -{ - memcpy(&msg->nm_src, addr, sizeof(*addr)); -} - -struct ucred * -nlmsg_get_creds(struct nl_msg *msg) -{ - if (msg->nm_creds_has) - return &msg->nm_creds; - return NULL; -} - -void -nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds) -{ - if (creds) { - memcpy(&msg->nm_creds, creds, sizeof(*creds)); - msg->nm_creds_has = TRUE; - } else - msg->nm_creds_has = FALSE; -} - -/*****************************************************************************/ - -void * -genlmsg_put(struct nl_msg *msg, - uint32_t port, - uint32_t seq, - int family, - int hdrlen, - int flags, - uint8_t cmd, - uint8_t version) -{ - struct nlmsghdr * nlh; - struct genlmsghdr hdr = { - .cmd = cmd, - .version = version, - }; - - nlh = nlmsg_put(msg, port, seq, family, GENL_HDRLEN + hdrlen, flags); - if (nlh == NULL) - return NULL; - - memcpy(nlmsg_data(nlh), &hdr, sizeof(hdr)); - - return (char *) nlmsg_data(nlh) + GENL_HDRLEN; -} - -void * -genlmsg_data(const struct genlmsghdr *gnlh) -{ - return ((unsigned char *) gnlh + GENL_HDRLEN); -} - -void * -genlmsg_user_hdr(const struct genlmsghdr *gnlh) -{ - return genlmsg_data(gnlh); -} - -struct genlmsghdr * -genlmsg_hdr(struct nlmsghdr *nlh) -{ - return nlmsg_data(nlh); -} - -void * -genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen) -{ - return (char *) genlmsg_user_hdr(gnlh) + NLMSG_ALIGN(hdrlen); -} - -struct nlattr * -genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen) -{ - return genlmsg_user_data(gnlh, hdrlen); -} - -int -genlmsg_len(const struct genlmsghdr *gnlh) -{ - const struct nlmsghdr *nlh; - - nlh = (const struct nlmsghdr *) ((const unsigned char *) gnlh - NLMSG_HDRLEN); - return (nlh->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN); -} - -int -genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen) -{ - return genlmsg_len(gnlh) - NLMSG_ALIGN(hdrlen); -} - -int -genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen) -{ - struct genlmsghdr *ghdr; - - if (!nlmsg_valid_hdr(nlh, GENL_HDRLEN)) - return 0; - - ghdr = nlmsg_data(nlh); - if (genlmsg_len(ghdr) < NLMSG_ALIGN(hdrlen)) - return 0; - - return 1; -} - -int -genlmsg_parse(struct nlmsghdr * nlh, - int hdrlen, - struct nlattr * tb[], - int maxtype, - const struct nla_policy *policy) -{ - struct genlmsghdr *ghdr; - - if (!genlmsg_valid_hdr(nlh, hdrlen)) - return -NME_NL_MSG_TOOSHORT; - - ghdr = nlmsg_data(nlh); - return nla_parse(tb, - maxtype, - genlmsg_attrdata(ghdr, hdrlen), - genlmsg_attrlen(ghdr, hdrlen), - policy); -} - -static int -_genl_parse_getfamily(struct nl_msg *msg, void *arg) -{ - static const struct nla_policy ctrl_policy[] = { - [CTRL_ATTR_FAMILY_ID] = {.type = NLA_U16}, - [CTRL_ATTR_FAMILY_NAME] = {.type = NLA_STRING, .maxlen = GENL_NAMSIZ}, - [CTRL_ATTR_VERSION] = {.type = NLA_U32}, - [CTRL_ATTR_HDRSIZE] = {.type = NLA_U32}, - [CTRL_ATTR_MAXATTR] = {.type = NLA_U32}, - [CTRL_ATTR_OPS] = {.type = NLA_NESTED}, - [CTRL_ATTR_MCAST_GROUPS] = {.type = NLA_NESTED}, - }; - struct nlattr * tb[G_N_ELEMENTS(ctrl_policy)]; - struct nlmsghdr *nlh = nlmsg_hdr(msg); - gint32 * response_data = arg; - - if (genlmsg_parse_arr(nlh, 0, tb, ctrl_policy) < 0) - return NL_SKIP; - - if (tb[CTRL_ATTR_FAMILY_ID]) - *response_data = nla_get_u16(tb[CTRL_ATTR_FAMILY_ID]); - - return NL_STOP; -} - -int -genl_ctrl_resolve(struct nl_sock *sk, const char *name) -{ - nm_auto_nlmsg struct nl_msg *msg = NULL; - int nmerr; - gint32 response_data = -1; - const struct nl_cb cb = { - .valid_cb = _genl_parse_getfamily, - .valid_arg = &response_data, - }; - - msg = nlmsg_alloc(); - - if (!genlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY, 1)) - return -ENOMEM; - - nmerr = nla_put_string(msg, CTRL_ATTR_FAMILY_NAME, name); - if (nmerr < 0) - return nmerr; - - nmerr = nl_send_auto(sk, msg); - if (nmerr < 0) - return nmerr; - - nmerr = nl_recvmsgs(sk, &cb); - if (nmerr < 0) - return nmerr; - - /* If search was successful, request may be ACKed after data */ - nmerr = nl_wait_for_ack(sk, NULL); - if (nmerr < 0) - return nmerr; - - if (response_data < 0) - return -NME_UNSPEC; - - return response_data; -} - -/*****************************************************************************/ - -struct nl_sock * -nl_socket_alloc(void) -{ - struct nl_sock *sk; - - sk = g_slice_new0(struct nl_sock); - - sk->s_fd = -1; - sk->s_local.nl_family = AF_NETLINK; - sk->s_peer.nl_family = AF_NETLINK; - sk->s_seq_expect = sk->s_seq_next = time(NULL); - - return sk; -} - -void -nl_socket_free(struct nl_sock *sk) -{ - if (!sk) - return; - - if (sk->s_fd >= 0) - nm_close(sk->s_fd); - g_slice_free(struct nl_sock, sk); -} - -int -nl_socket_get_fd(const struct nl_sock *sk) -{ - return sk->s_fd; -} - -uint32_t -nl_socket_get_local_port(const struct nl_sock *sk) -{ - return sk->s_local.nl_pid; -} - -size_t -nl_socket_get_msg_buf_size(struct nl_sock *sk) -{ - return sk->s_bufsize; -} - -int -nl_socket_set_passcred(struct nl_sock *sk, int state) -{ - int err; - - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; - - err = setsockopt(sk->s_fd, SOL_SOCKET, SO_PASSCRED, &state, sizeof(state)); - if (err < 0) - return -nm_errno_from_native(errno); - - if (state) - sk->s_flags |= NL_SOCK_PASSCRED; - else - sk->s_flags &= ~NL_SOCK_PASSCRED; - - return 0; -} - -int -nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize) -{ - sk->s_bufsize = bufsize; - - return 0; -} - -struct sockaddr_nl * -nlmsg_get_dst(struct nl_msg *msg) -{ - return &msg->nm_dst; -} - -int -nl_socket_set_nonblocking(const struct nl_sock *sk) -{ - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; - - if (fcntl(sk->s_fd, F_SETFL, O_NONBLOCK) < 0) - return -nm_errno_from_native(errno); - - return 0; -} - -int -nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf) -{ - int err; - - if (rxbuf <= 0) - rxbuf = 32768; - - if (txbuf <= 0) - txbuf = 32768; - - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; - - err = setsockopt(sk->s_fd, SOL_SOCKET, SO_SNDBUF, &txbuf, sizeof(txbuf)); - if (err < 0) { - return -nm_errno_from_native(errno); - } - - err = setsockopt(sk->s_fd, SOL_SOCKET, SO_RCVBUF, &rxbuf, sizeof(rxbuf)); - if (err < 0) { - return -nm_errno_from_native(errno); - } - - return 0; -} - -int -nl_socket_add_memberships(struct nl_sock *sk, int group, ...) -{ - int err; - va_list ap; - - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; - - va_start(ap, group); - - while (group != 0) { - if (group < 0) { - va_end(ap); - g_return_val_if_reached(-NME_BUG); - } - - err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group, sizeof(group)); - if (err < 0) { - int errsv = errno; - - va_end(ap); - return -nm_errno_from_native(errsv); - } - - group = va_arg(ap, int); - } - - va_end(ap); - - return 0; -} - -int -nl_socket_set_ext_ack(struct nl_sock *sk, gboolean enable) -{ - int err, val; - - if (sk->s_fd == -1) - return -NME_NL_BAD_SOCK; - - val = !!enable; - err = setsockopt(sk->s_fd, SOL_NETLINK, NETLINK_EXT_ACK, &val, sizeof(val)); - if (err < 0) - return -nm_errno_from_native(errno); - - return 0; -} - -void -nl_socket_disable_msg_peek(struct nl_sock *sk) -{ - sk->s_flags |= NL_MSG_PEEK_EXPLICIT; - sk->s_flags &= ~NL_MSG_PEEK; -} - -int -nl_connect(struct nl_sock *sk, int protocol) -{ - int err, nmerr; - socklen_t addrlen; - struct sockaddr_nl local = {0}; - - if (sk->s_fd != -1) - return -NME_NL_BAD_SOCK; - - sk->s_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, protocol); - if (sk->s_fd < 0) { - nmerr = -nm_errno_from_native(errno); - goto errout; - } - - nmerr = nl_socket_set_buffer_size(sk, 0, 0); - if (nmerr < 0) - goto errout; - - nm_assert(sk->s_local.nl_pid == 0); - - err = bind(sk->s_fd, (struct sockaddr *) &sk->s_local, sizeof(sk->s_local)); - if (err != 0) { - nmerr = -nm_errno_from_native(errno); - goto errout; - } - - addrlen = sizeof(local); - err = getsockname(sk->s_fd, (struct sockaddr *) &local, &addrlen); - if (err < 0) { - nmerr = -nm_errno_from_native(errno); - goto errout; - } - - if (addrlen != sizeof(local)) { - nmerr = -NME_UNSPEC; - goto errout; - } - - if (local.nl_family != AF_NETLINK) { - nmerr = -NME_UNSPEC; - goto errout; - } - - sk->s_local = local; - sk->s_proto = protocol; - - return 0; - -errout: - if (sk->s_fd != -1) { - close(sk->s_fd); - sk->s_fd = -1; - } - return nmerr; -} - -/*****************************************************************************/ - -static void -_cb_init(struct nl_cb *dst, const struct nl_cb *src) -{ - nm_assert(dst); - - if (src) - *dst = *src; - else - memset(dst, 0, sizeof(*dst)); -} - -static int -ack_wait_handler(struct nl_msg *msg, void *arg) -{ - return NL_STOP; -} - -int -nl_wait_for_ack(struct nl_sock *sk, const struct nl_cb *cb) -{ - struct nl_cb cb2; - - _cb_init(&cb2, cb); - cb2.ack_cb = ack_wait_handler; - return nl_recvmsgs(sk, &cb2); -} - -#define NL_CB_CALL(cb, type, msg) \ - do { \ - const struct nl_cb *_cb = (cb); \ - \ - if (_cb && _cb->type##_cb) { \ - /* the returned value here must be either a negative - * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ \ - nmerr = _cb->type##_cb((msg), _cb->type##_arg); \ - switch (nmerr) { \ - case NL_OK: \ - nm_assert(nmerr == 0); \ - break; \ - case NL_SKIP: \ - goto skip; \ - case NL_STOP: \ - goto stop; \ - default: \ - if (nmerr >= 0) { \ - nm_assert_not_reached(); \ - nmerr = -NME_BUG; \ - } \ - goto out; \ - } \ - } \ - } while (0) - -int -nl_recvmsgs(struct nl_sock *sk, const struct nl_cb *cb) -{ - int n, nmerr = 0, multipart = 0, interrupted = 0, nrecv = 0; - gs_free unsigned char *buf = NULL; - struct nlmsghdr * hdr; - struct sockaddr_nl nla = {0}; - struct ucred creds; - gboolean creds_has; - -continue_reading: - n = nl_recv(sk, &nla, &buf, &creds, &creds_has); - if (n <= 0) - return n; - - hdr = (struct nlmsghdr *) buf; - while (nlmsg_ok(hdr, n)) { - nm_auto_nlmsg struct nl_msg *msg = NULL; - - msg = nlmsg_alloc_convert(hdr); - - nlmsg_set_proto(msg, sk->s_proto); - nlmsg_set_src(msg, &nla); - nlmsg_set_creds(msg, creds_has ? &creds : NULL); - - nrecv++; - - /* Only do sequence checking if auto-ack mode is enabled */ - if (!(sk->s_flags & NL_NO_AUTO_ACK)) { - if (hdr->nlmsg_seq != sk->s_seq_expect) { - nmerr = -NME_NL_SEQ_MISMATCH; - goto out; - } - } - - if (hdr->nlmsg_type == NLMSG_DONE || hdr->nlmsg_type == NLMSG_ERROR - || hdr->nlmsg_type == NLMSG_NOOP || hdr->nlmsg_type == NLMSG_OVERRUN) { - /* We can't check for !NLM_F_MULTI since some netlink - * users in the kernel are broken. */ - sk->s_seq_expect++; - } - - if (hdr->nlmsg_flags & NLM_F_MULTI) - multipart = 1; - - if (hdr->nlmsg_flags & NLM_F_DUMP_INTR) { - /* - * We have to continue reading to clear - * all messages until a NLMSG_DONE is - * received and report the inconsistency. - */ - interrupted = 1; - } - - /* messages terminates a multipart message, this is - * usually the end of a message and therefore we slip - * out of the loop by default. the user may overrule - * this action by skipping this packet. */ - if (hdr->nlmsg_type == NLMSG_DONE) { - multipart = 0; - NL_CB_CALL(cb, finish, msg); - } - - /* Message to be ignored, the default action is to - * skip this message if no callback is specified. The - * user may overrule this action by returning - * NL_PROCEED. */ - else if (hdr->nlmsg_type == NLMSG_NOOP) - goto skip; - - /* Data got lost, report back to user. The default action is to - * quit parsing. The user may overrule this action by returning - * NL_SKIP or NL_PROCEED (dangerous) */ - else if (hdr->nlmsg_type == NLMSG_OVERRUN) { - nmerr = -NME_NL_MSG_OVERFLOW; - goto out; - } - - /* Message carries a nlmsgerr */ - else if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *e = nlmsg_data(hdr); - - if (hdr->nlmsg_len < nlmsg_size(sizeof(*e))) { - /* Truncated error message, the default action - * is to stop parsing. The user may overrule - * this action by returning NL_SKIP or - * NL_PROCEED (dangerous) */ - nmerr = -NME_NL_MSG_TRUNC; - goto out; - } - if (e->error) { - /* Error message reported back from kernel. */ - if (cb && cb->err_cb) { - /* the returned value here must be either a negative - * netlink error number, or one of NL_SKIP, NL_STOP, NL_OK. */ - nmerr = cb->err_cb(&nla, e, cb->err_arg); - if (nmerr < 0) - goto out; - else if (nmerr == NL_SKIP) - goto skip; - else if (nmerr == NL_STOP) { - nmerr = -nm_errno_from_native(e->error); - goto out; - } - nm_assert(nmerr == NL_OK); - } else { - nmerr = -nm_errno_from_native(e->error); - goto out; - } - } else - NL_CB_CALL(cb, ack, msg); - } else { - /* Valid message (not checking for MULTIPART bit to - * get along with broken kernels. NL_SKIP has no - * effect on this. */ - NL_CB_CALL(cb, valid, msg); - } -skip: - nmerr = 0; - hdr = nlmsg_next(hdr, &n); - } - - if (multipart) { - /* Multipart message not yet complete, continue reading */ - nm_clear_g_free(&buf); - - nmerr = 0; - goto continue_reading; - } - -stop: - nmerr = 0; - -out: - if (interrupted) - nmerr = -NME_NL_DUMP_INTR; - - nm_assert(nmerr <= 0); - return nmerr ?: nrecv; -} - -int -nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr) -{ - int ret; - - if (sk->s_fd < 0) - return -NME_NL_BAD_SOCK; - - nlmsg_set_src(msg, &sk->s_local); - - ret = sendmsg(sk->s_fd, hdr, 0); - if (ret < 0) - return -nm_errno_from_native(errno); - - return ret; -} - -int -nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen) -{ - struct sockaddr_nl *dst; - struct ucred * creds; - struct msghdr hdr = { - .msg_name = (void *) &sk->s_peer, - .msg_namelen = sizeof(struct sockaddr_nl), - .msg_iov = iov, - .msg_iovlen = iovlen, - }; - char buf[CMSG_SPACE(sizeof(struct ucred))]; - - /* Overwrite destination if specified in the message itself, defaults - * to the peer address of the socket. - */ - dst = nlmsg_get_dst(msg); - if (dst->nl_family == AF_NETLINK) - hdr.msg_name = dst; - - /* Add credentials if present. */ - creds = nlmsg_get_creds(msg); - if (creds != NULL) { - struct cmsghdr *cmsg; - - hdr.msg_control = buf; - hdr.msg_controllen = sizeof(buf); - - cmsg = CMSG_FIRSTHDR(&hdr); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_CREDENTIALS; - cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred)); - memcpy(CMSG_DATA(cmsg), creds, sizeof(struct ucred)); - } - - return nl_sendmsg(sk, msg, &hdr); -} - -void -nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg) -{ - struct nlmsghdr *nlh; - - nlh = nlmsg_hdr(msg); - if (nlh->nlmsg_pid == NL_AUTO_PORT) - nlh->nlmsg_pid = nl_socket_get_local_port(sk); - - if (nlh->nlmsg_seq == NL_AUTO_SEQ) - nlh->nlmsg_seq = sk->s_seq_next++; - - if (msg->nm_protocol == -1) - msg->nm_protocol = sk->s_proto; - - nlh->nlmsg_flags |= NLM_F_REQUEST; - - if (!(sk->s_flags & NL_NO_AUTO_ACK)) - nlh->nlmsg_flags |= NLM_F_ACK; -} - -int -nl_send(struct nl_sock *sk, struct nl_msg *msg) -{ - struct iovec iov = { - .iov_base = (void *) nlmsg_hdr(msg), - .iov_len = nlmsg_hdr(msg)->nlmsg_len, - }; - - return nl_send_iovec(sk, msg, &iov, 1); -} - -int -nl_send_auto(struct nl_sock *sk, struct nl_msg *msg) -{ - nl_complete_msg(sk, msg); - - return nl_send(sk, msg); -} - -int -nl_recv(struct nl_sock * sk, - struct sockaddr_nl *nla, - unsigned char ** buf, - struct ucred * out_creds, - gboolean * out_creds_has) -{ - ssize_t n; - int flags = 0; - struct iovec iov; - struct msghdr msg = { - .msg_name = (void *) nla, - .msg_namelen = sizeof(struct sockaddr_nl), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - struct ucred tmpcreds; - gboolean tmpcreds_has = FALSE; - int retval; - int errsv; - - nm_assert(nla); - nm_assert(buf && !*buf); - nm_assert(!out_creds_has == !out_creds); - - if ((sk->s_flags & NL_MSG_PEEK) - || (!(sk->s_flags & NL_MSG_PEEK_EXPLICIT) && sk->s_bufsize == 0)) - flags |= MSG_PEEK | MSG_TRUNC; - - iov.iov_len = sk->s_bufsize ?: (((size_t) nm_utils_getpagesize()) * 4u); - iov.iov_base = g_malloc(iov.iov_len); - - if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { - msg.msg_controllen = CMSG_SPACE(sizeof(struct ucred)); - msg.msg_control = g_malloc(msg.msg_controllen); - } - -retry: - n = recvmsg(sk->s_fd, &msg, flags); - if (!n) { - retval = 0; - goto abort; - } - - if (n < 0) { - errsv = errno; - if (errsv == EINTR) - goto retry; - retval = -nm_errno_from_native(errsv); - goto abort; - } - - if (msg.msg_flags & MSG_CTRUNC) { - if (msg.msg_controllen == 0) { - retval = -NME_NL_MSG_TRUNC; - goto abort; - } - - msg.msg_controllen *= 2; - msg.msg_control = g_realloc(msg.msg_control, msg.msg_controllen); - goto retry; - } - - if (iov.iov_len < n || (msg.msg_flags & MSG_TRUNC)) { - /* respond with error to an incomplete message */ - if (flags == 0) { - retval = -NME_NL_MSG_TRUNC; - goto abort; - } - - /* Provided buffer is not long enough, enlarge it - * to size of n (which should be total length of the message) - * and try again. */ - iov.iov_base = g_realloc(iov.iov_base, n); - iov.iov_len = n; - flags = 0; - goto retry; - } - - if (flags != 0) { - /* Buffer is big enough, do the actual reading */ - flags = 0; - goto retry; - } - - if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { - retval = -NME_UNSPEC; - goto abort; - } - - if (out_creds && (sk->s_flags & NL_SOCK_PASSCRED)) { - struct cmsghdr *cmsg; - - for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_level != SOL_SOCKET) - continue; - if (cmsg->cmsg_type != SCM_CREDENTIALS) - continue; - memcpy(&tmpcreds, CMSG_DATA(cmsg), sizeof(tmpcreds)); - tmpcreds_has = TRUE; - break; - } - } - - retval = n; - -abort: - g_free(msg.msg_control); - - if (retval <= 0) { - g_free(iov.iov_base); - return retval; - } - - *buf = iov.iov_base; - if (out_creds && tmpcreds_has) - *out_creds = tmpcreds; - NM_SET_OUT(out_creds_has, tmpcreds_has); - return retval; -} diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h deleted file mode 100644 index 52283e9f..00000000 --- a/src/platform/nm-netlink.h +++ /dev/null @@ -1,616 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2018 Red Hat, Inc. - */ - -#ifndef __NM_NETLINK_H__ -#define __NM_NETLINK_H__ - -#include <linux/netlink.h> -#include <linux/rtnetlink.h> -#include <linux/genetlink.h> - -#include "nm-std-aux/unaligned.h" - -/*****************************************************************************/ - -#define NLMSGERR_ATTR_UNUSED 0 -#define NLMSGERR_ATTR_MSG 1 -#define NLMSGERR_ATTR_OFFS 2 -#define NLMSGERR_ATTR_COOKIE 3 -#define NLMSGERR_ATTR_MAX 3 - -#ifndef NLM_F_ACK_TLVS - #define NLM_F_ACK_TLVS 0x200 -#endif - -/*****************************************************************************/ - -/* Basic attribute data types */ -enum { - NLA_UNSPEC, /* Unspecified type, binary data chunk */ - NLA_U8, /* 8 bit integer */ - NLA_U16, /* 16 bit integer */ - NLA_U32, /* 32 bit integer */ - NLA_U64, /* 64 bit integer */ - NLA_STRING, /* NUL terminated character string */ - NLA_FLAG, /* Flag */ - NLA_MSECS, /* Micro seconds (64bit) */ - NLA_NESTED, /* Nested attributes */ - NLA_NESTED_COMPAT, - NLA_NUL_STRING, - NLA_BINARY, - NLA_S8, - NLA_S16, - NLA_S32, - NLA_S64, - __NLA_TYPE_MAX, -}; - -#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) - -struct nl_msg; - -/*****************************************************************************/ - -const char *nl_nlmsgtype2str(int type, char *buf, size_t size); - -const char *nl_nlmsg_flags2str(int flags, char *buf, size_t len); - -const char *nl_nlmsghdr_to_str(const struct nlmsghdr *hdr, char *buf, gsize len); - -/*****************************************************************************/ - -struct nla_policy { - /* Type of attribute or NLA_UNSPEC */ - uint16_t type; - - /* Minimal length of payload required */ - uint16_t minlen; - - /* Maximal length of payload allowed */ - uint16_t maxlen; -}; - -/*****************************************************************************/ - -/* static asserts that @tb and @policy are suitable arguments to nla_parse(). */ -#define _nl_static_assert_tb(tb, policy) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(tb) > 0); \ - \ - /* We allow @policy to be either a C array or NULL. The sizeof() - * must either match the expected array size or the sizeof(NULL), - * but not both. */ \ - G_STATIC_ASSERT_EXPR((sizeof(policy) == G_N_ELEMENTS(tb) * sizeof(struct nla_policy)) \ - ^ (sizeof(policy) == sizeof(NULL))); \ - } \ - G_STMT_END - -/*****************************************************************************/ - -static inline int -nla_attr_size(int payload) -{ - nm_assert(payload >= 0); - - return NLA_HDRLEN + payload; -} - -static inline int -nla_total_size(int payload) -{ - return NLA_ALIGN(nla_attr_size(payload)); -} - -static inline int -nla_padlen(int payload) -{ - return nla_total_size(payload) - nla_attr_size(payload); -} - -struct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int attrlen); - -static inline int -nla_len(const struct nlattr *nla) -{ - nm_assert(nla); - nm_assert(nla->nla_len >= NLA_HDRLEN); - - return ((int) nla->nla_len) - NLA_HDRLEN; -} - -static inline int -nla_type(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= 0); - - return nla->nla_type & NLA_TYPE_MASK; -} - -static inline void * -nla_data(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= 0); - - return &(((char *) nla)[NLA_HDRLEN]); -} - -#define nla_data_as(type, nla) \ - ({ \ - const struct nlattr *_nla = (nla); \ - \ - nm_assert(nla_len(_nla) >= sizeof(type)); \ - \ - /* note that casting the pointer is undefined behavior in C, if - * the data has wrong alignment. Netlink data is aligned to 4 bytes, - * that means, if the alignment is larger than 4, this is invalid. */ \ - G_STATIC_ASSERT_EXPR(_nm_alignof(type) <= NLA_ALIGNTO); \ - \ - (type *) nla_data(_nla); \ - }) - -static inline uint8_t -nla_get_u8(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(uint8_t)); - - return *((const uint8_t *) nla_data(nla)); -} - -static inline int8_t -nla_get_s8(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(int8_t)); - - return *((const int8_t *) nla_data(nla)); -} - -static inline uint8_t -nla_get_u8_cond(/*const*/ struct nlattr *const *tb, int attr, uint8_t default_val) -{ - nm_assert(tb); - nm_assert(attr >= 0); - - return tb[attr] ? nla_get_u8(tb[attr]) : default_val; -} - -static inline uint16_t -nla_get_u16(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(uint16_t)); - - return *((const uint16_t *) nla_data(nla)); -} - -static inline uint32_t -nla_get_u32(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(uint32_t)); - - return *((const uint32_t *) nla_data(nla)); -} - -static inline int32_t -nla_get_s32(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(int32_t)); - - return *((const int32_t *) nla_data(nla)); -} - -static inline uint64_t -nla_get_u64(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(uint64_t)); - - return unaligned_read_ne64(nla_data(nla)); -} - -static inline uint64_t -nla_get_be64(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= sizeof(uint64_t)); - - return unaligned_read_be64(nla_data(nla)); -} - -static inline char * -nla_get_string(const struct nlattr *nla) -{ - nm_assert(nla_len(nla) >= 0); - - return (char *) nla_data(nla); -} - -size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize); - -size_t nla_memcpy(void *dst, const struct nlattr *nla, size_t dstsize); - -#define nla_memcpy_checked_size(dst, nla, dstsize) \ - G_STMT_START \ - { \ - void *const _dst = (dst); \ - const struct nlattr *const _nla = (nla); \ - const size_t _dstsize = (dstsize); \ - size_t _srcsize; \ - \ - /* assert that, if @nla is given, that it has the exact expected - * size. This implies that the caller previously verified the length - * of the attribute (via minlen/maxlen at nla_parse()). */ \ - \ - if (_nla) { \ - _srcsize = nla_memcpy(_dst, _nla, _dstsize); \ - nm_assert(_srcsize == _dstsize); \ - } \ - } \ - G_STMT_END - -int nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data); - -static inline int -nla_put_string(struct nl_msg *msg, int attrtype, const char *str) -{ - nm_assert(str); - - return nla_put(msg, attrtype, strlen(str) + 1, str); -} - -static inline int -nla_put_uint8(struct nl_msg *msg, int attrtype, uint8_t val) -{ - return nla_put(msg, attrtype, sizeof(val), &val); -} - -static inline int -nla_put_uint16(struct nl_msg *msg, int attrtype, uint16_t val) -{ - return nla_put(msg, attrtype, sizeof(val), &val); -} - -static inline int -nla_put_uint32(struct nl_msg *msg, int attrtype, uint32_t val) -{ - return nla_put(msg, attrtype, sizeof(val), &val); -} - -#define NLA_PUT(msg, attrtype, attrlen, data) \ - G_STMT_START \ - { \ - if (nla_put(msg, attrtype, attrlen, data) < 0) \ - goto nla_put_failure; \ - } \ - G_STMT_END - -#define NLA_PUT_TYPE(msg, type, attrtype, value) \ - G_STMT_START \ - { \ - type __nla_tmp = value; \ - NLA_PUT(msg, attrtype, sizeof(type), &__nla_tmp); \ - } \ - G_STMT_END - -#define NLA_PUT_U8(msg, attrtype, value) NLA_PUT_TYPE(msg, uint8_t, attrtype, value) - -#define NLA_PUT_S8(msg, attrtype, value) NLA_PUT_TYPE(msg, int8_t, attrtype, value) - -#define NLA_PUT_U16(msg, attrtype, value) NLA_PUT_TYPE(msg, uint16_t, attrtype, value) - -#define NLA_PUT_U32(msg, attrtype, value) NLA_PUT_TYPE(msg, uint32_t, attrtype, value) - -#define NLA_PUT_S32(msg, attrtype, value) NLA_PUT_TYPE(msg, int32_t, attrtype, value) - -#define NLA_PUT_U64(msg, attrtype, value) NLA_PUT_TYPE(msg, uint64_t, attrtype, value) - -#define NLA_PUT_STRING(msg, attrtype, value) NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value) - -#define NLA_PUT_FLAG(msg, attrtype) NLA_PUT(msg, attrtype, 0, NULL) - -struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype); - -static inline int -nla_ok(const struct nlattr *nla, int remaining) -{ - return remaining >= (int) sizeof(*nla) && nla->nla_len >= sizeof(*nla) - && nla->nla_len <= remaining; -} - -static inline struct nlattr * -nla_next(const struct nlattr *nla, int *remaining) -{ - int totlen = NLA_ALIGN(nla->nla_len); - - *remaining -= totlen; - return (struct nlattr *) ((char *) nla + totlen); -} - -#define nla_for_each_attr(pos, head, len, rem) \ - for (pos = head, rem = len; nla_ok(pos, rem); pos = nla_next(pos, &(rem))) - -#define nla_for_each_nested(pos, nla, rem) \ - for (pos = (struct nlattr *) nla_data(nla), rem = nla_len(nla); nla_ok(pos, rem); \ - pos = nla_next(pos, &(rem))) - -void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr); -struct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype); -int nla_nest_end(struct nl_msg *msg, struct nlattr *start); - -int nla_parse(struct nlattr * tb[], - int maxtype, - struct nlattr * head, - int len, - const struct nla_policy *policy); - -#define nla_parse_arr(tb, head, len, policy) \ - ({ \ - _nl_static_assert_tb((tb), (policy)); \ - \ - nla_parse((tb), G_N_ELEMENTS(tb) - 1, (head), (len), (policy)); \ - }) - -static inline int -nla_parse_nested(struct nlattr * tb[], - int maxtype, - struct nlattr * nla, - const struct nla_policy *policy) -{ - return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); -} - -#define nla_parse_nested_arr(tb, nla, policy) \ - ({ \ - _nl_static_assert_tb((tb), (policy)); \ - \ - nla_parse_nested((tb), G_N_ELEMENTS(tb) - 1, (nla), (policy)); \ - }) - -/*****************************************************************************/ - -struct nl_msg *nlmsg_alloc(void); - -struct nl_msg *nlmsg_alloc_size(size_t max); - -struct nl_msg *nlmsg_alloc_convert(struct nlmsghdr *hdr); - -struct nl_msg *nlmsg_alloc_simple(int nlmsgtype, int flags); - -void *nlmsg_reserve(struct nl_msg *n, size_t len, int pad); - -int nlmsg_append(struct nl_msg *n, const void *data, size_t len, int pad); - -#define nlmsg_append_struct(n, data) nlmsg_append(n, (data), sizeof(*(data)), NLMSG_ALIGNTO) - -void nlmsg_free(struct nl_msg *msg); - -static inline int -nlmsg_size(int payload) -{ - nm_assert(payload >= 0 && payload < G_MAXINT - NLMSG_HDRLEN - 4); - return NLMSG_HDRLEN + payload; -} - -static inline int -nlmsg_total_size(int payload) -{ - return NLMSG_ALIGN(nlmsg_size(payload)); -} - -static inline int -nlmsg_ok(const struct nlmsghdr *nlh, int remaining) -{ - return (remaining >= (int) sizeof(struct nlmsghdr) && nlh->nlmsg_len >= sizeof(struct nlmsghdr) - && nlh->nlmsg_len <= remaining); -} - -static inline struct nlmsghdr * -nlmsg_next(struct nlmsghdr *nlh, int *remaining) -{ - int totlen = NLMSG_ALIGN(nlh->nlmsg_len); - - *remaining -= totlen; - - return (struct nlmsghdr *) ((unsigned char *) nlh + totlen); -} - -int nlmsg_get_proto(struct nl_msg *msg); -void nlmsg_set_proto(struct nl_msg *msg, int protocol); - -void nlmsg_set_src(struct nl_msg *msg, struct sockaddr_nl *addr); - -struct ucred *nlmsg_get_creds(struct nl_msg *msg); -void nlmsg_set_creds(struct nl_msg *msg, struct ucred *creds); - -static inline void -_nm_auto_nl_msg_cleanup(struct nl_msg **ptr) -{ - nlmsg_free(*ptr); -} -#define nm_auto_nlmsg nm_auto(_nm_auto_nl_msg_cleanup) - -static inline void * -nlmsg_data(const struct nlmsghdr *nlh) -{ - return (unsigned char *) nlh + NLMSG_HDRLEN; -} - -static inline void * -nlmsg_tail(const struct nlmsghdr *nlh) -{ - return (unsigned char *) nlh + NLMSG_ALIGN(nlh->nlmsg_len); -} - -struct nlmsghdr *nlmsg_hdr(struct nl_msg *n); - -static inline int -nlmsg_valid_hdr(const struct nlmsghdr *nlh, int hdrlen) -{ - if (nlh->nlmsg_len < nlmsg_size(hdrlen)) - return 0; - - return 1; -} - -static inline int -nlmsg_datalen(const struct nlmsghdr *nlh) -{ - return nlh->nlmsg_len - NLMSG_HDRLEN; -} - -static inline int -nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen) -{ - return NM_MAX((int) (nlmsg_datalen(nlh) - NLMSG_ALIGN(hdrlen)), 0); -} - -static inline struct nlattr * -nlmsg_attrdata(const struct nlmsghdr *nlh, int hdrlen) -{ - unsigned char *data = nlmsg_data(nlh); - return (struct nlattr *) (data + NLMSG_ALIGN(hdrlen)); -} - -static inline struct nlattr * -nlmsg_find_attr(struct nlmsghdr *nlh, int hdrlen, int attrtype) -{ - return nla_find(nlmsg_attrdata(nlh, hdrlen), nlmsg_attrlen(nlh, hdrlen), attrtype); -} - -int nlmsg_parse(struct nlmsghdr * nlh, - int hdrlen, - struct nlattr * tb[], - int maxtype, - const struct nla_policy *policy); - -#define nlmsg_parse_arr(nlh, hdrlen, tb, policy) \ - ({ \ - _nl_static_assert_tb((tb), (policy)); \ - G_STATIC_ASSERT_EXPR((hdrlen) >= 0); \ - \ - nlmsg_parse((nlh), (hdrlen), (tb), G_N_ELEMENTS(tb) - 1, (policy)); \ - }) - -struct nlmsghdr * -nlmsg_put(struct nl_msg *n, uint32_t pid, uint32_t seq, int type, int payload, int flags); - -/*****************************************************************************/ - -#define NL_AUTO_PORT 0 -#define NL_AUTO_SEQ 0 - -struct nl_sock; - -struct nl_sock *nl_socket_alloc(void); - -void nl_socket_free(struct nl_sock *sk); - -int nl_socket_get_fd(const struct nl_sock *sk); - -struct sockaddr_nl *nlmsg_get_dst(struct nl_msg *msg); - -size_t nl_socket_get_msg_buf_size(struct nl_sock *sk); -int nl_socket_set_msg_buf_size(struct nl_sock *sk, size_t bufsize); - -int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf); - -int nl_socket_set_passcred(struct nl_sock *sk, int state); - -int nl_socket_set_nonblocking(const struct nl_sock *sk); - -void nl_socket_disable_msg_peek(struct nl_sock *sk); - -uint32_t nl_socket_get_local_port(const struct nl_sock *sk); - -int nl_socket_add_memberships(struct nl_sock *sk, int group, ...); - -int nl_connect(struct nl_sock *sk, int protocol); - -int nl_recv(struct nl_sock * sk, - struct sockaddr_nl *nla, - unsigned char ** buf, - struct ucred * out_creds, - gboolean * out_creds_has); - -int nl_send(struct nl_sock *sk, struct nl_msg *msg); - -int nl_send_auto(struct nl_sock *sk, struct nl_msg *msg); - -/*****************************************************************************/ - -enum nl_cb_action { - /* Proceed with wathever would come next */ - NL_OK, - /* Skip this message */ - NL_SKIP, - /* Stop parsing altogether and discard remaining messages */ - NL_STOP, -}; - -typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg); - -typedef int (*nl_recvmsg_err_cb_t)(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg); - -struct nl_cb { - nl_recvmsg_msg_cb_t valid_cb; - void * valid_arg; - - nl_recvmsg_msg_cb_t finish_cb; - void * finish_arg; - - nl_recvmsg_msg_cb_t ack_cb; - void * ack_arg; - - nl_recvmsg_err_cb_t err_cb; - void * err_arg; -}; - -int nl_sendmsg(struct nl_sock *sk, struct nl_msg *msg, struct msghdr *hdr); - -int nl_send_iovec(struct nl_sock *sk, struct nl_msg *msg, struct iovec *iov, unsigned iovlen); - -void nl_complete_msg(struct nl_sock *sk, struct nl_msg *msg); - -int nl_recvmsgs(struct nl_sock *sk, const struct nl_cb *cb); - -int nl_wait_for_ack(struct nl_sock *sk, const struct nl_cb *cb); - -int nl_socket_set_ext_ack(struct nl_sock *sk, gboolean enable); - -/*****************************************************************************/ - -void * genlmsg_put(struct nl_msg *msg, - uint32_t port, - uint32_t seq, - int family, - int hdrlen, - int flags, - uint8_t cmd, - uint8_t version); -void * genlmsg_data(const struct genlmsghdr *gnlh); -void * genlmsg_user_hdr(const struct genlmsghdr *gnlh); -struct genlmsghdr *genlmsg_hdr(struct nlmsghdr *nlh); -void * genlmsg_user_data(const struct genlmsghdr *gnlh, const int hdrlen); -struct nlattr * genlmsg_attrdata(const struct genlmsghdr *gnlh, int hdrlen); -int genlmsg_len(const struct genlmsghdr *gnlh); -int genlmsg_attrlen(const struct genlmsghdr *gnlh, int hdrlen); -int genlmsg_valid_hdr(struct nlmsghdr *nlh, int hdrlen); - -int genlmsg_parse(struct nlmsghdr * nlh, - int hdrlen, - struct nlattr * tb[], - int maxtype, - const struct nla_policy *policy); - -#define genlmsg_parse_arr(nlh, hdrlen, tb, policy) \ - ({ \ - _nl_static_assert_tb((tb), (policy)); \ - G_STATIC_ASSERT_EXPR((hdrlen) >= 0); \ - \ - genlmsg_parse((nlh), (hdrlen), (tb), G_N_ELEMENTS(tb) - 1, (policy)); \ - }) - -int genl_ctrl_resolve(struct nl_sock *sk, const char *name); - -/*****************************************************************************/ - -#endif /* __NM_NETLINK_H__ */ diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c deleted file mode 100644 index ea45050d..00000000 --- a/src/platform/nm-platform-utils.c +++ /dev/null @@ -1,1785 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-platform-utils.h" - -#include <unistd.h> -#include <sys/ioctl.h> -#include <linux/ethtool.h> -#include <linux/sockios.h> -#include <linux/mii.h> -#include <linux/if.h> -#include <linux/version.h> -#include <linux/rtnetlink.h> -#include <fcntl.h> -#include <libudev.h> - -#include "nm-utils.h" -#include "nm-setting-wired.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" - -#include "nm-core-utils.h" - -#define ONOFF(bool_val) ((bool_val) ? "on" : "off") - -/****************************************************************************** - * utils - *****************************************************************************/ - -extern char *if_indextoname(unsigned __ifindex, char *__ifname); -unsigned if_nametoindex(const char *__ifname); - -const char * -nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/) -{ - g_return_val_if_fail(ifindex > 0, NULL); - g_return_val_if_fail(out_ifname, NULL); - - return if_indextoname(ifindex, out_ifname); -} - -int -nmp_utils_if_nametoindex(const char *ifname) -{ - g_return_val_if_fail(ifname, 0); - - return if_nametoindex(ifname); -} - -/*****************************************************************************/ - -typedef struct { - int fd; - const int ifindex; - char ifname[IFNAMSIZ]; -} SocketHandle; - -#define SOCKET_HANDLE_INIT(_ifindex) \ - { \ - .fd = -1, .ifindex = (_ifindex), \ - } - -static void -_nm_auto_socket_handle(SocketHandle *shandle) -{ - if (shandle->fd >= 0) - nm_close(shandle->fd); -} - -#define nm_auto_socket_handle nm_auto(_nm_auto_socket_handle) - -/*****************************************************************************/ - -typedef enum { - IOCTL_CALL_DATA_TYPE_NONE, - IOCTL_CALL_DATA_TYPE_IFRDATA, - IOCTL_CALL_DATA_TYPE_IFRU, -} IoctlCallDataType; - -static int -_ioctl_call(const char * log_ioctl_type, - const char * log_subtype, - unsigned long int ioctl_request, - int ifindex, - int * inout_fd, - char * inout_ifname, - IoctlCallDataType edata_type, - gpointer edata, - gsize edata_size, - struct ifreq * out_ifreq) -{ - nm_auto_close int fd_close = -1; - int fd; - int r; - gpointer edata_backup = NULL; - gs_free gpointer edata_backup_free = NULL; - guint try_count; - char known_ifnames[2][IFNAMSIZ]; - const char * failure_reason = NULL; - struct ifreq ifr; - - nm_assert(ifindex > 0); - nm_assert(NM_IN_SET(edata_type, - IOCTL_CALL_DATA_TYPE_NONE, - IOCTL_CALL_DATA_TYPE_IFRDATA, - IOCTL_CALL_DATA_TYPE_IFRU)); - nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_NONE || edata_size == 0); - nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRDATA || edata_size > 0); - nm_assert(edata_type != IOCTL_CALL_DATA_TYPE_IFRU - || (edata_size > 0 && edata_size <= sizeof(ifr.ifr_ifru))); - nm_assert(edata_size == 0 || edata); - - /* open a file descriptor (or use the one provided). */ - if (inout_fd && *inout_fd >= 0) - fd = *inout_fd; - else { - fd = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - r = -NM_ERRNO_NATIVE(errno); - failure_reason = "failed creating socket or ioctl"; - goto out; - } - if (inout_fd) - *inout_fd = fd; - else - fd_close = fd; - } - - /* resolve the ifindex to name (or use the one provided). */ - if (inout_ifname && inout_ifname[0]) - nm_utils_ifname_cpy(known_ifnames[0], inout_ifname); - else { - if (!nmp_utils_if_indextoname(ifindex, known_ifnames[0])) { - failure_reason = "cannot resolve ifindex"; - r = -ENODEV; - goto out; - } - if (inout_ifname) - nm_utils_ifname_cpy(inout_ifname, known_ifnames[0]); - } - - /* we might need to retry the request. Backup edata so that we can - * restore it on retry. */ - if (edata_size > 0) - edata_backup = nm_memdup_maybe_a(500, edata, edata_size, &edata_backup_free); - - try_count = 0; - -again: -{ - const char *ifname = known_ifnames[try_count % 2]; - - nm_assert(ifindex > 0); - nm_assert(ifname && nm_utils_ifname_valid_kernel(ifname, NULL)); - nm_assert(fd >= 0); - - memset(&ifr, 0, sizeof(ifr)); - nm_utils_ifname_cpy(ifr.ifr_name, ifname); - if (edata_type == IOCTL_CALL_DATA_TYPE_IFRDATA) - ifr.ifr_data = edata; - else if (edata_type == IOCTL_CALL_DATA_TYPE_IFRU) - memcpy(&ifr.ifr_ifru, edata, NM_MIN(edata_size, sizeof(ifr.ifr_ifru))); - - if (ioctl(fd, ioctl_request, &ifr) < 0) { - r = -NM_ERRNO_NATIVE(errno); - nm_log_trace(LOGD_PLATFORM, - "%s[%d]: %s, %s: failed: %s", - log_ioctl_type, - ifindex, - log_subtype, - ifname, - nm_strerror_native(-r)); - } else { - r = 0; - nm_log_trace(LOGD_PLATFORM, - "%s[%d]: %s, %s: success", - log_ioctl_type, - ifindex, - log_subtype, - ifname); - } -} - - try_count++; - - /* resolve the name again to see whether the ifindex still has the same name. */ - if (!nmp_utils_if_indextoname(ifindex, known_ifnames[try_count % 2])) { - /* we could not find the ifindex again. Probably the device just got - * removed. - * - * In both cases we return the error code we got from ioctl above. - * Either it failed because the device was gone already or it still - * managed to complete the call. In both cases, the error code is good. */ - failure_reason = - "cannot resolve ifindex after ioctl call. Probably the device was just removed"; - goto out; - } - - /* check whether the ifname changed in the meantime. If yes, would render the result - * invalid. Note that this cannot detect every race regarding renames, for example: - * - * - if_indextoname(#10) gives eth0 - * - rename(#10) => eth0_tmp - * - rename(#11) => eth0 - * - ioctl(eth0) (wrongly fetching #11, formerly eth1) - * - rename(#11) => eth_something - * - rename(#10) => eth0 - * - if_indextoname(#10) gives eth0 - */ - if (!nm_streq(known_ifnames[0], known_ifnames[1])) { - gboolean retry; - - /* we detected a possible(!) rename. - * - * For getters it's straight forward to just retry the call. - * - * For setters we also always retry. If our previous call operated on the right device, - * calling it again should have no bad effect (just setting the same thing more than once). - * - * The only potential bad thing is if there was a race involving swapping names, and we just - * set the ioctl option on the wrong device. But then the bad thing already happenned and - * we cannot detect it (nor do anything about it). At least, we can retry and set the - * option on the right interface. */ - retry = (try_count < 5); - - nm_log_trace(LOGD_PLATFORM, - "%s[%d]: %s: rename detected from \"%s\" to \"%s\". %s", - log_ioctl_type, - ifindex, - log_subtype, - known_ifnames[(try_count - 1) % 2], - known_ifnames[try_count % 2], - retry ? "Retry" : "No retry"); - if (inout_ifname) - nm_utils_ifname_cpy(inout_ifname, known_ifnames[try_count % 2]); - if (retry) { - if (edata_size > 0) - memcpy(edata, edata_backup, edata_size); - goto again; - } - } - -out: - if (failure_reason) { - nm_log_trace(LOGD_PLATFORM, - "%s[%d]: %s: %s: %s", - log_ioctl_type, - ifindex, - log_subtype, - failure_reason, - r < 0 ? nm_strerror_native(-r) : "assume success"); - } - if (r >= 0) - NM_SET_OUT(out_ifreq, ifr); - return r; -} - -/****************************************************************************** - * ethtool - *****************************************************************************/ - -static NM_UTILS_ENUM2STR_DEFINE(_ethtool_cmd_to_string, - guint32, - NM_UTILS_ENUM2STR(ETHTOOL_GCOALESCE, "ETHTOOL_GCOALESCE"), - NM_UTILS_ENUM2STR(ETHTOOL_GDRVINFO, "ETHTOOL_GDRVINFO"), - NM_UTILS_ENUM2STR(ETHTOOL_GFEATURES, "ETHTOOL_GFEATURES"), - NM_UTILS_ENUM2STR(ETHTOOL_GLINK, "ETHTOOL_GLINK"), - NM_UTILS_ENUM2STR(ETHTOOL_GPERMADDR, "ETHTOOL_GPERMADDR"), - NM_UTILS_ENUM2STR(ETHTOOL_GRINGPARAM, "ETHTOOL_GRINGPARAM"), - NM_UTILS_ENUM2STR(ETHTOOL_GSET, "ETHTOOL_GSET"), - NM_UTILS_ENUM2STR(ETHTOOL_GSSET_INFO, "ETHTOOL_GSSET_INFO"), - NM_UTILS_ENUM2STR(ETHTOOL_GSTATS, "ETHTOOL_GSTATS"), - NM_UTILS_ENUM2STR(ETHTOOL_GSTRINGS, "ETHTOOL_GSTRINGS"), - NM_UTILS_ENUM2STR(ETHTOOL_GWOL, "ETHTOOL_GWOL"), - NM_UTILS_ENUM2STR(ETHTOOL_SCOALESCE, "ETHTOOL_SCOALESCE"), - NM_UTILS_ENUM2STR(ETHTOOL_SFEATURES, "ETHTOOL_SFEATURES"), - NM_UTILS_ENUM2STR(ETHTOOL_SRINGPARAM, "ETHTOOL_SRINGPARAM"), - NM_UTILS_ENUM2STR(ETHTOOL_SSET, "ETHTOOL_SSET"), - NM_UTILS_ENUM2STR(ETHTOOL_SWOL, "ETHTOOL_SWOL"), ); - -static const char * -_ethtool_edata_to_string(gpointer edata, gsize edata_size, char *sbuf, gsize sbuf_len) -{ - nm_assert(edata); - nm_assert(edata_size >= sizeof(guint32)); - nm_assert((((intptr_t) edata) % _nm_alignof(guint32)) == 0); - - return _ethtool_cmd_to_string(*((guint32 *) edata), sbuf, sbuf_len); -} - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) - #define ethtool_cmd_speed(pedata) ((pedata)->speed) - - #define ethtool_cmd_speed_set(pedata, speed) \ - G_STMT_START \ - { \ - (pedata)->speed = (guint16)(speed); \ - } \ - G_STMT_END -#endif - -static int -_ethtool_call_handle(SocketHandle *shandle, gpointer edata, gsize edata_size) -{ - char sbuf[50]; - - return _ioctl_call("ethtool", - _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)), - SIOCETHTOOL, - shandle->ifindex, - &shandle->fd, - shandle->ifname, - IOCTL_CALL_DATA_TYPE_IFRDATA, - edata, - edata_size, - NULL); -} - -static int -_ethtool_call_once(int ifindex, gpointer edata, gsize edata_size) -{ - char sbuf[50]; - - return _ioctl_call("ethtool", - _ethtool_edata_to_string(edata, edata_size, sbuf, sizeof(sbuf)), - SIOCETHTOOL, - ifindex, - NULL, - NULL, - IOCTL_CALL_DATA_TYPE_IFRDATA, - edata, - edata_size, - NULL); -} - -/*****************************************************************************/ - -static struct ethtool_gstrings * -ethtool_get_stringset(SocketHandle *shandle, int stringset_id) -{ - struct { - struct ethtool_sset_info info; - guint32 sentinel; - } sset_info = { - .info.cmd = ETHTOOL_GSSET_INFO, - .info.reserved = 0, - .info.sset_mask = (1ULL << stringset_id), - }; - const guint32 * pdata; - gs_free struct ethtool_gstrings *gstrings = NULL; - gsize gstrings_len; - guint32 i, len; - - if (_ethtool_call_handle(shandle, &sset_info, sizeof(sset_info)) < 0) - return NULL; - if (!sset_info.info.sset_mask) - return NULL; - - pdata = (guint32 *) sset_info.info.data; - - len = *pdata; - - gstrings_len = sizeof(*gstrings) + (len * ETH_GSTRING_LEN); - gstrings = g_malloc0(gstrings_len); - gstrings->cmd = ETHTOOL_GSTRINGS; - gstrings->string_set = stringset_id; - gstrings->len = len; - if (gstrings->len > 0) { - if (_ethtool_call_handle(shandle, gstrings, gstrings_len) < 0) - return NULL; - for (i = 0; i < gstrings->len; i++) { - /* ensure NUL terminated */ - gstrings->data[i * ETH_GSTRING_LEN + (ETH_GSTRING_LEN - 1)] = '\0'; - } - } - - return g_steal_pointer(&gstrings); -} - -static int -ethtool_gstrings_find(const struct ethtool_gstrings *gstrings, const char *needle) -{ - guint32 i; - - /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. - * that means, we cannot possibly request longer names. */ - nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN); - - for (i = 0; i < gstrings->len; i++) { - if (nm_streq((char *) &gstrings->data[i * ETH_GSTRING_LEN], needle)) - return i; - } - return -1; -} - -static int -ethtool_get_stringset_index(SocketHandle *shandle, int stringset_id, const char *needle) -{ - gs_free struct ethtool_gstrings *gstrings = NULL; - - /* ethtool_get_stringset() always ensures NUL terminated strings at ETH_GSTRING_LEN. - * that means, we cannot possibly request longer names. */ - nm_assert(needle && strlen(needle) < ETH_GSTRING_LEN); - - gstrings = ethtool_get_stringset(shandle, stringset_id); - if (gstrings) - return ethtool_gstrings_find(gstrings, needle); - return -1; -} - -/*****************************************************************************/ - -static const NMEthtoolFeatureInfo _ethtool_feature_infos[_NM_ETHTOOL_ID_FEATURE_NUM] = { -#define ETHT_FEAT(eid, ...) \ - { \ - .ethtool_id = eid, .n_kernel_names = NM_NARG(__VA_ARGS__), \ - .kernel_names = ((const char *const[]){__VA_ARGS__}), \ - } - - /* the order does only matter for one thing: if it happens that more than one NMEthtoolID - * reference the same kernel-name, then the one that is mentioned *later* will win in - * case these NMEthtoolIDs are set. That mostly only makes sense for ethtool-ids which - * refer to multiple features ("feature-tso"), while also having more specific ids - * ("feature-tx-tcp-segmentation"). */ - - /* names from ethtool utility, which are aliases for multiple features. */ - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_SG, "tx-scatter-gather", "tx-scatter-gather-fraglist"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TSO, - "tx-tcp-segmentation", - "tx-tcp-ecn-segmentation", - "tx-tcp-mangleid-segmentation", - "tx-tcp6-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX, - "tx-checksum-ipv4", - "tx-checksum-ip-generic", - "tx-checksum-ipv6", - "tx-checksum-fcoe-crc", - "tx-checksum-sctp"), - - /* names from ethtool utility, which are aliases for one feature. */ - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GRO, "rx-gro"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_GSO, "tx-generic-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LRO, "rx-lro"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_NTUPLE, "rx-ntuple-filter"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX, "rx-checksum"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXHASH, "rx-hashing"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RXVLAN, "rx-vlan-hw-parse"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TXVLAN, "tx-vlan-hw-insert"), - - /* names of features, as known by kernel. */ - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_HW_OFFLOAD, "esp-hw-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_ESP_TX_CSUM_HW_OFFLOAD, "esp-tx-csum-hw-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_FCOE_MTU, "fcoe-mtu"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HIGHDMA, "highdma"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_HW_TC_OFFLOAD, "hw-tc-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_L2_FWD_OFFLOAD, "l2-fwd-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_LOOPBACK, "loopback"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_ALL, "rx-all"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_FCS, "rx-fcs"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_GRO_HW, "rx-gro-hw"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_UDP_TUNNEL_PORT_OFFLOAD, "rx-udp_tunnel-port-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_FILTER, "rx-vlan-filter"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_FILTER, "rx-vlan-stag-filter"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_RX_VLAN_STAG_HW_PARSE, "rx-vlan-stag-hw-parse"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_RECORD, "tls-hw-record"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TLS_HW_TX_OFFLOAD, "tls-hw-tx-offload"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_FCOE_CRC, "tx-checksum-fcoe-crc"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV4, "tx-checksum-ipv4"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IPV6, "tx-checksum-ipv6"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_IP_GENERIC, "tx-checksum-ip-generic"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_CHECKSUM_SCTP, "tx-checksum-sctp"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_ESP_SEGMENTATION, "tx-esp-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_FCOE_SEGMENTATION, "tx-fcoe-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_CSUM_SEGMENTATION, "tx-gre-csum-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GRE_SEGMENTATION, "tx-gre-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_PARTIAL, "tx-gso-partial"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_GSO_ROBUST, "tx-gso-robust"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP4_SEGMENTATION, "tx-ipxip4-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_IPXIP6_SEGMENTATION, "tx-ipxip6-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_NOCACHE_COPY, "tx-nocache-copy"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER, "tx-scatter-gather"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCATTER_GATHER_FRAGLIST, "tx-scatter-gather-fraglist"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_SCTP_SEGMENTATION, "tx-sctp-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP6_SEGMENTATION, "tx-tcp6-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_ECN_SEGMENTATION, "tx-tcp-ecn-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_MANGLEID_SEGMENTATION, "tx-tcp-mangleid-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_TCP_SEGMENTATION, "tx-tcp-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_SEGMENTATION, "tx-udp-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_CSUM_SEGMENTATION, "tx-udp_tnl-csum-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_UDP_TNL_SEGMENTATION, "tx-udp_tnl-segmentation"), - ETHT_FEAT(NM_ETHTOOL_ID_FEATURE_TX_VLAN_STAG_HW_INSERT, "tx-vlan-stag-hw-insert"), -}; - -/* the number of kernel features that we handle. It essentially is the sum of all - * kernel_names. So, all ethtool-ids that reference exactly one kernel-name - * (_NM_ETHTOOL_ID_FEATURE_NUM) + some extra, for ethtool-ids that are aliases - * for multiple kernel-names. */ -#define N_ETHTOOL_KERNEL_FEATURES (((guint) _NM_ETHTOOL_ID_FEATURE_NUM) + 8u) - -static void -_ASSERT_ethtool_feature_infos(void) -{ -#if NM_MORE_ASSERTS > 10 - guint i, k, n; - bool found[_NM_ETHTOOL_ID_FEATURE_NUM] = {}; - - G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(_ethtool_feature_infos) == _NM_ETHTOOL_ID_FEATURE_NUM); - - n = 0; - for (i = 0; i < G_N_ELEMENTS(_ethtool_feature_infos); i++) { - NMEthtoolFeatureState kstate; - const NMEthtoolFeatureInfo *inf = &_ethtool_feature_infos[i]; - - g_assert(inf->ethtool_id >= _NM_ETHTOOL_ID_FEATURE_FIRST); - g_assert(inf->ethtool_id <= _NM_ETHTOOL_ID_FEATURE_LAST); - g_assert(inf->n_kernel_names > 0); - - for (k = 0; k < i; k++) - g_assert(inf->ethtool_id != _ethtool_feature_infos[k].ethtool_id); - - g_assert(!found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)]); - found[_NM_ETHTOOL_ID_FEATURE_AS_IDX(inf->ethtool_id)] = TRUE; - - kstate.idx_kernel_name = inf->n_kernel_names - 1; - g_assert((guint) kstate.idx_kernel_name == (guint)(inf->n_kernel_names - 1)); - - n += inf->n_kernel_names; - for (k = 0; k < inf->n_kernel_names; k++) { - g_assert(nm_utils_strv_find_first((char **) inf->kernel_names, k, inf->kernel_names[k]) - < 0); - } - } - - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) - g_assert(found[i]); - - g_assert(n == N_ETHTOOL_KERNEL_FEATURES); -#endif -} - -static NMEthtoolFeatureStates * -ethtool_get_features(SocketHandle *shandle) -{ - gs_free NMEthtoolFeatureStates * states = NULL; - gs_free struct ethtool_gstrings *ss_features = NULL; - - _ASSERT_ethtool_feature_infos(); - - ss_features = ethtool_get_stringset(shandle, ETH_SS_FEATURES); - if (!ss_features) - return NULL; - - if (ss_features->len > 0) { - gs_free struct ethtool_gfeatures * gfeatures_free = NULL; - struct ethtool_gfeatures * gfeatures; - gsize gfeatures_len; - guint idx; - const NMEthtoolFeatureState * states_list0 = NULL; - const NMEthtoolFeatureState *const *states_plist0 = NULL; - guint states_plist_n = 0; - - gfeatures_len = sizeof(struct ethtool_gfeatures) - + (NM_DIV_ROUND_UP(ss_features->len, 32u) * sizeof(gfeatures->features[0])); - gfeatures = nm_malloc0_maybe_a(300, gfeatures_len, &gfeatures_free); - gfeatures->cmd = ETHTOOL_GFEATURES; - gfeatures->size = NM_DIV_ROUND_UP(ss_features->len, 32u); - if (_ethtool_call_handle(shandle, gfeatures, gfeatures_len) < 0) - return NULL; - - for (idx = 0; idx < G_N_ELEMENTS(_ethtool_feature_infos); idx++) { - const NMEthtoolFeatureInfo *info = &_ethtool_feature_infos[idx]; - guint idx_kernel_name; - - for (idx_kernel_name = 0; idx_kernel_name < info->n_kernel_names; idx_kernel_name++) { - NMEthtoolFeatureState *kstate; - const char * kernel_name = info->kernel_names[idx_kernel_name]; - int i_feature; - guint i_block; - guint32 i_flag; - - i_feature = ethtool_gstrings_find(ss_features, kernel_name); - if (i_feature < 0) - continue; - - i_block = ((guint) i_feature) / 32u; - i_flag = (guint32)(1u << (((guint) i_feature) % 32u)); - - if (!states) { - states = g_malloc0( - sizeof(NMEthtoolFeatureStates) - + (N_ETHTOOL_KERNEL_FEATURES * sizeof(NMEthtoolFeatureState)) - + ((N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)) - * sizeof(NMEthtoolFeatureState *))); - states_list0 = &states->states_list[0]; - states_plist0 = (gpointer) &states_list0[N_ETHTOOL_KERNEL_FEATURES]; - states->n_ss_features = ss_features->len; - } - - nm_assert(states->n_states < N_ETHTOOL_KERNEL_FEATURES); - kstate = (NMEthtoolFeatureState *) &states_list0[states->n_states]; - states->n_states++; - - kstate->info = info; - kstate->idx_ss_features = i_feature; - kstate->idx_kernel_name = idx_kernel_name; - kstate->available = !!(gfeatures->features[i_block].available & i_flag); - kstate->requested = !!(gfeatures->features[i_block].requested & i_flag); - kstate->active = !!(gfeatures->features[i_block].active & i_flag); - kstate->never_changed = !!(gfeatures->features[i_block].never_changed & i_flag); - - nm_assert(states_plist_n - < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)); - - if (!states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)]) - states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)] = - &states_plist0[states_plist_n]; - ((const NMEthtoolFeatureState **) states_plist0)[states_plist_n] = kstate; - states_plist_n++; - } - - if (states && states->states_indexed[_NM_ETHTOOL_ID_FEATURE_AS_IDX(info->ethtool_id)]) { - nm_assert(states_plist_n - < N_ETHTOOL_KERNEL_FEATURES + G_N_ELEMENTS(_ethtool_feature_infos)); - nm_assert(!states_plist0[states_plist_n]); - states_plist_n++; - } - } - } - - return g_steal_pointer(&states); -} - -NMEthtoolFeatureStates * -nmp_utils_ethtool_get_features(int ifindex) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - NMEthtoolFeatureStates * features; - - g_return_val_if_fail(ifindex > 0, 0); - - features = ethtool_get_features(&shandle); - - if (!features) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting features", - ifindex, - "get-features"); - return NULL; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: retrieved kernel features", - ifindex, - "get-features"); - return features; -} - -static const char * -_ethtool_feature_state_to_string(char * buf, - gsize buf_size, - const NMEthtoolFeatureState *s, - const char * prefix) -{ - int l; - - l = g_snprintf(buf, - buf_size, - "%s %s%s", - prefix ?: "", - ONOFF(s->active), - (!s->available || s->never_changed) - ? ", [fixed]" - : ((s->requested != s->active) - ? (s->requested ? ", [requested on]" : ", [requested off]") - : "")); - nm_assert(l < buf_size); - return buf; -} - -gboolean -nmp_utils_ethtool_set_features( - int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - gs_free struct ethtool_sfeatures * sfeatures_free = NULL; - struct ethtool_sfeatures * sfeatures; - gsize sfeatures_len; - int r; - guint i, j; - struct { - const NMEthtoolFeatureState *f_state; - NMTernary requested; - } set_states[N_ETHTOOL_KERNEL_FEATURES]; - guint set_states_n = 0; - gboolean success = TRUE; - - g_return_val_if_fail(ifindex > 0, 0); - g_return_val_if_fail(features, 0); - g_return_val_if_fail(requested, 0); - - nm_assert(features->n_states <= N_ETHTOOL_KERNEL_FEATURES); - - for (i = 0; i < _NM_ETHTOOL_ID_FEATURE_NUM; i++) { - const NMEthtoolFeatureState *const *states_indexed; - - if (requested[i] == NM_TERNARY_DEFAULT) - continue; - - if (!(states_indexed = features->states_indexed[i])) { - if (do_set) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: set feature %s: skip (not found)", - ifindex, - "set-features", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname); - success = FALSE; - } - continue; - } - - for (j = 0; states_indexed[j]; j++) { - const NMEthtoolFeatureState *s = states_indexed[j]; - char sbuf[255]; - - if (set_states_n >= G_N_ELEMENTS(set_states)) - g_return_val_if_reached(FALSE); - - if (s->never_changed) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: %s feature %s (%s): %s, %s (skip feature marked as " - "never changed)", - ifindex, - "set-features", - do_set ? "set" : "reset", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, - s->info->kernel_names[s->idx_kernel_name], - ONOFF(do_set ? requested[i] == NM_TERNARY_TRUE : s->active), - _ethtool_feature_state_to_string(sbuf, - sizeof(sbuf), - s, - do_set ? " currently:" : " before:")); - continue; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: %s feature %s (%s): %s, %s", - ifindex, - "set-features", - do_set ? "set" : "reset", - nm_ethtool_data[i + _NM_ETHTOOL_ID_FEATURE_FIRST]->optname, - s->info->kernel_names[s->idx_kernel_name], - ONOFF(do_set ? requested[i] == NM_TERNARY_TRUE : s->active), - _ethtool_feature_state_to_string(sbuf, - sizeof(sbuf), - s, - do_set ? " currently:" : " before:")); - - if (do_set && (!s->available || s->never_changed) - && (s->active != (requested[i] == NM_TERNARY_TRUE))) { - /* we request to change a flag which kernel reported as fixed. - * While the ethtool operation will silently succeed, mark the request - * as failure. */ - success = FALSE; - } - - set_states[set_states_n].f_state = s; - set_states[set_states_n].requested = requested[i]; - set_states_n++; - } - } - - if (set_states_n == 0) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: no feature requested", - ifindex, - "set-features"); - return TRUE; - } - - sfeatures_len = - sizeof(struct ethtool_sfeatures) - + (NM_DIV_ROUND_UP(features->n_ss_features, 32U) * sizeof(sfeatures->features[0])); - sfeatures = nm_malloc0_maybe_a(300, sfeatures_len, &sfeatures_free); - sfeatures->cmd = ETHTOOL_SFEATURES; - sfeatures->size = NM_DIV_ROUND_UP(features->n_ss_features, 32U); - - for (i = 0; i < set_states_n; i++) { - const NMEthtoolFeatureState *s = set_states[i].f_state; - guint i_block; - guint32 i_flag; - gboolean is_requested; - - i_block = s->idx_ss_features / 32u; - i_flag = (guint32)(1u << (s->idx_ss_features % 32u)); - - sfeatures->features[i_block].valid |= i_flag; - - if (do_set) - is_requested = (set_states[i].requested == NM_TERNARY_TRUE); - else - is_requested = s->active; - - if (is_requested) - sfeatures->features[i_block].requested |= i_flag; - else - sfeatures->features[i_block].requested &= ~i_flag; - } - - r = _ethtool_call_handle(&shandle, sfeatures, sfeatures_len); - if (r < 0) { - success = FALSE; - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure setting features (%s)", - ifindex, - "set-features", - nm_strerror_native(-r)); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: %s", - ifindex, - "set-features", - success ? "successfully setting features" - : "at least some of the features were not successfully set"); - return success; -} - -static gboolean -ethtool_get_coalesce(SocketHandle *shandle, NMEthtoolCoalesceState *coalesce) -{ - struct ethtool_coalesce eth_data; - - eth_data.cmd = ETHTOOL_GCOALESCE; - - if (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_coalesce)) != 0) - return FALSE; - - *coalesce = (NMEthtoolCoalesceState){ - .s = { - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)] = - eth_data.rx_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)] = - eth_data.rx_max_coalesced_frames, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)] = - eth_data.rx_coalesce_usecs_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)] = - eth_data.rx_max_coalesced_frames_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)] = - eth_data.tx_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)] = - eth_data.tx_max_coalesced_frames, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)] = - eth_data.tx_coalesce_usecs_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)] = - eth_data.tx_max_coalesced_frames_irq, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)] = - eth_data.stats_block_coalesce_usecs, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)] = - eth_data.use_adaptive_rx_coalesce, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)] = - eth_data.use_adaptive_tx_coalesce, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)] = - eth_data.pkt_rate_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)] = - eth_data.rx_coalesce_usecs_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)] = - eth_data.rx_max_coalesced_frames_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)] = - eth_data.tx_coalesce_usecs_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)] = - eth_data.tx_max_coalesced_frames_low, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)] = - eth_data.pkt_rate_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)] = - eth_data.rx_coalesce_usecs_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)] = - eth_data.rx_max_coalesced_frames_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)] = - eth_data.tx_coalesce_usecs_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)] = - eth_data.tx_max_coalesced_frames_high, - [_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)] = - eth_data.rate_sample_interval, - }}; - return TRUE; -} - -gboolean -nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(coalesce, FALSE); - - if (!ethtool_get_coalesce(&shandle, coalesce)) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting coalesce settings", - ifindex, - "get-coalesce"); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: retrieved kernel coalesce settings", - ifindex, - "get-coalesce"); - return TRUE; -} - -static gboolean -ethtool_set_coalesce(SocketHandle *shandle, const NMEthtoolCoalesceState *coalesce) -{ - struct ethtool_coalesce eth_data; - gboolean success; - - nm_assert(shandle); - nm_assert(coalesce); - - eth_data = (struct ethtool_coalesce){ - .cmd = ETHTOOL_SCOALESCE, - .rx_coalesce_usecs = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS)], - .rx_max_coalesced_frames = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES)], - .rx_coalesce_usecs_irq = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_IRQ)], - .rx_max_coalesced_frames_irq = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_IRQ)], - .tx_coalesce_usecs = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS)], - .tx_max_coalesced_frames = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES)], - .tx_coalesce_usecs_irq = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_IRQ)], - .tx_max_coalesced_frames_irq = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_IRQ)], - .stats_block_coalesce_usecs = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_STATS_BLOCK_USECS)], - .use_adaptive_rx_coalesce = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_RX)], - .use_adaptive_tx_coalesce = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_ADAPTIVE_TX)], - .pkt_rate_low = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_LOW)], - .rx_coalesce_usecs_low = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_LOW)], - .rx_max_coalesced_frames_low = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_LOW)], - .tx_coalesce_usecs_low = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_LOW)], - .tx_max_coalesced_frames_low = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_LOW)], - .pkt_rate_high = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_PKT_RATE_HIGH)], - .rx_coalesce_usecs_high = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_USECS_HIGH)], - .rx_max_coalesced_frames_high = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_RX_FRAMES_HIGH)], - .tx_coalesce_usecs_high = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_USECS_HIGH)], - .tx_max_coalesced_frames_high = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_TX_FRAMES_HIGH)], - .rate_sample_interval = - coalesce->s[_NM_ETHTOOL_ID_COALESCE_AS_IDX(NM_ETHTOOL_ID_COALESCE_SAMPLE_INTERVAL)], - }; - - success = (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_coalesce)) == 0); - return success; -} - -gboolean -nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(coalesce, FALSE); - - if (!ethtool_set_coalesce(&shandle, coalesce)) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure setting coalesce settings", - ifindex, - "set-coalesce"); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: set kernel coalesce settings", - ifindex, - "set-coalesce"); - return TRUE; -} - -static gboolean -ethtool_get_ring(SocketHandle *shandle, NMEthtoolRingState *ring) -{ - struct ethtool_ringparam eth_data; - - eth_data.cmd = ETHTOOL_GRINGPARAM; - - if (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_ringparam)) != 0) - return FALSE; - - ring->rx_pending = eth_data.rx_pending; - ring->rx_jumbo_pending = eth_data.rx_jumbo_pending; - ring->rx_mini_pending = eth_data.rx_mini_pending; - ring->tx_pending = eth_data.tx_pending; - - return TRUE; -} - -gboolean -nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ring, FALSE); - - if (!ethtool_get_ring(&shandle, ring)) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure getting ring settings", - ifindex, - "get-ring"); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: retrieved kernel ring settings", - ifindex, - "get-ring"); - return TRUE; -} - -static gboolean -ethtool_set_ring(SocketHandle *shandle, const NMEthtoolRingState *ring) -{ - gboolean success; - struct ethtool_ringparam eth_data; - - g_return_val_if_fail(shandle, FALSE); - g_return_val_if_fail(ring, FALSE); - - eth_data = (struct ethtool_ringparam){ - .cmd = ETHTOOL_SRINGPARAM, - .rx_pending = ring->rx_pending, - .rx_jumbo_pending = ring->rx_jumbo_pending, - .rx_mini_pending = ring->rx_mini_pending, - .tx_pending = ring->tx_pending, - }; - - success = (_ethtool_call_handle(shandle, ð_data, sizeof(struct ethtool_ringparam)) == 0); - return success; -} - -gboolean -nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(ring, FALSE); - - if (!ethtool_set_ring(&shandle, ring)) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %s: failure setting ring settings", - ifindex, - "set-ring"); - return FALSE; - } - - nm_log_trace(LOGD_PLATFORM, "ethtool[%d]: %s: set kernel ring settings", ifindex, "set-ring"); - return TRUE; -} - -/*****************************************************************************/ - -gboolean -nmp_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data) -{ - struct ethtool_drvinfo *drvinfo; - - G_STATIC_ASSERT_EXPR(sizeof(*data) == sizeof(*drvinfo)); - G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, driver) - == offsetof(struct ethtool_drvinfo, driver)); - G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, version) - == offsetof(struct ethtool_drvinfo, version)); - G_STATIC_ASSERT_EXPR(offsetof(NMPUtilsEthtoolDriverInfo, fw_version) - == offsetof(struct ethtool_drvinfo, fw_version)); - G_STATIC_ASSERT_EXPR(sizeof(data->driver) == sizeof(drvinfo->driver)); - G_STATIC_ASSERT_EXPR(sizeof(data->version) == sizeof(drvinfo->version)); - G_STATIC_ASSERT_EXPR(sizeof(data->fw_version) == sizeof(drvinfo->fw_version)); - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail(data, FALSE); - - drvinfo = (struct ethtool_drvinfo *) data; - *drvinfo = (struct ethtool_drvinfo){ - .cmd = ETHTOOL_GDRVINFO, - }; - return _ethtool_call_once(ifindex, drvinfo, sizeof(*drvinfo)) >= 0; -} - -gboolean -nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length) -{ - struct { - struct ethtool_perm_addr e; - guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1]; - } edata = { - .e.cmd = ETHTOOL_GPERMADDR, - .e.size = NM_UTILS_HWADDR_LEN_MAX, - }; - const guint8 *pdata; - - guint i; - - g_return_val_if_fail(ifindex > 0, FALSE); - - if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0) - return FALSE; - - if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX) - return FALSE; - if (edata.e.size < 1) - return FALSE; - - pdata = (const guint8 *) edata.e.data; - - if (NM_IN_SET(pdata[0], 0, 0xFF)) { - /* Some drivers might return a permanent address of all zeros. - * Reject that (rh#1264024) - * - * Some drivers return a permanent address of all ones. Reject that too */ - for (i = 1; i < edata.e.size; i++) { - if (pdata[0] != pdata[i]) - goto not_all_0or1; - } - return FALSE; - } - -not_all_0or1: - memcpy(buf, pdata, edata.e.size); - *length = edata.e.size; - return TRUE; -} - -gboolean -nmp_utils_ethtool_supports_carrier_detect(int ifindex) -{ - struct ethtool_cmd edata = {.cmd = ETHTOOL_GLINK}; - - g_return_val_if_fail(ifindex > 0, FALSE); - - /* We ignore the result. If the ETHTOOL_GLINK call succeeded, then we - * assume the device supports carrier-detect, otherwise we assume it - * doesn't. - */ - return _ethtool_call_once(ifindex, &edata, sizeof(edata)) >= 0; -} - -gboolean -nmp_utils_ethtool_supports_vlans(int ifindex) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - gs_free struct ethtool_gfeatures * features_free = NULL; - struct ethtool_gfeatures * features; - gsize features_len; - int idx, block, bit, size; - - g_return_val_if_fail(ifindex > 0, FALSE); - - idx = ethtool_get_stringset_index(&shandle, ETH_SS_FEATURES, "vlan-challenged"); - if (idx < 0) { - nm_log_dbg(LOGD_PLATFORM, - "ethtool[%d]: vlan-challenged ethtool feature does not exist?", - ifindex); - return FALSE; - } - - block = idx / 32; - bit = idx % 32; - size = block + 1; - - features_len = sizeof(*features) + (size * sizeof(struct ethtool_get_features_block)); - features = nm_malloc0_maybe_a(300, features_len, &features_free); - features->cmd = ETHTOOL_GFEATURES; - features->size = size; - - if (_ethtool_call_handle(&shandle, features, features_len) < 0) - return FALSE; - - return !(features->features[block].active & (1 << bit)); -} - -int -nmp_utils_ethtool_get_peer_ifindex(int ifindex) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - gsize stats_len; - gs_free struct ethtool_stats * stats_free = NULL; - struct ethtool_stats * stats; - int peer_ifindex_stat; - - g_return_val_if_fail(ifindex > 0, 0); - - peer_ifindex_stat = ethtool_get_stringset_index(&shandle, ETH_SS_STATS, "peer_ifindex"); - if (peer_ifindex_stat < 0) { - nm_log_dbg(LOGD_PLATFORM, "ethtool[%d]: peer_ifindex stat does not exist?", ifindex); - return FALSE; - } - - stats_len = sizeof(*stats) + (peer_ifindex_stat + 1) * sizeof(guint64); - stats = nm_malloc0_maybe_a(300, stats_len, &stats_free); - stats->cmd = ETHTOOL_GSTATS; - stats->n_stats = peer_ifindex_stat + 1; - if (_ethtool_call_handle(&shandle, stats, stats_len) < 0) - return 0; - - return stats->data[peer_ifindex_stat]; -} - -gboolean -nmp_utils_ethtool_get_wake_on_lan(int ifindex) -{ - struct ethtool_wolinfo wol = { - .cmd = ETHTOOL_GWOL, - }; - - g_return_val_if_fail(ifindex > 0, FALSE); - - if (_ethtool_call_once(ifindex, &wol, sizeof(wol)) < 0) - return FALSE; - - return wol.wolopts != 0; -} - -gboolean -nmp_utils_ethtool_get_link_settings(int ifindex, - gboolean * out_autoneg, - guint32 * out_speed, - NMPlatformLinkDuplexType *out_duplex) -{ - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; - - g_return_val_if_fail(ifindex > 0, FALSE); - - if (_ethtool_call_once(ifindex, &edata, sizeof(edata)) < 0) - return FALSE; - - NM_SET_OUT(out_autoneg, (edata.autoneg == AUTONEG_ENABLE)); - - if (out_speed) { - guint32 speed; - - speed = ethtool_cmd_speed(&edata); - if (speed == G_MAXUINT16 || speed == G_MAXUINT32) - speed = 0; - - *out_speed = speed; - } - - if (out_duplex) { - switch (edata.duplex) { - case DUPLEX_HALF: - *out_duplex = NM_PLATFORM_LINK_DUPLEX_HALF; - break; - case DUPLEX_FULL: - *out_duplex = NM_PLATFORM_LINK_DUPLEX_FULL; - break; - default: /* DUPLEX_UNKNOWN */ - *out_duplex = NM_PLATFORM_LINK_DUPLEX_UNKNOWN; - break; - } - } - - return TRUE; -} - -#define ADVERTISED_INVALID 0 -#define BASET_ALL_MODES \ - (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Half \ - | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full \ - | ADVERTISED_10000baseT_Full) - -static guint32 -get_baset_mode(guint32 speed, NMPlatformLinkDuplexType duplex) -{ - if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN) - return ADVERTISED_INVALID; - - if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) { - switch (speed) { - case 10: - return ADVERTISED_10baseT_Half; - case 100: - return ADVERTISED_100baseT_Half; - case 1000: - return ADVERTISED_1000baseT_Half; - default: - return ADVERTISED_INVALID; - } - } else { - switch (speed) { - case 10: - return ADVERTISED_10baseT_Full; - case 100: - return ADVERTISED_100baseT_Full; - case 1000: - return ADVERTISED_1000baseT_Full; - case 10000: - return ADVERTISED_10000baseT_Full; - default: - return ADVERTISED_INVALID; - } - } -} - -gboolean -nmp_utils_ethtool_set_link_settings(int ifindex, - gboolean autoneg, - guint32 speed, - NMPlatformLinkDuplexType duplex) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - struct ethtool_cmd edata = { - .cmd = ETHTOOL_GSET, - }; - - g_return_val_if_fail(ifindex > 0, FALSE); - g_return_val_if_fail((speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN) - || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), - FALSE); - - /* retrieve first current settings */ - if (_ethtool_call_handle(&shandle, &edata, sizeof(edata)) < 0) - return FALSE; - - /* FIXME: try first new ETHTOOL_GLINKSETTINGS/SLINKSETTINGS API - * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=3f1ac7a700d039c61d8d8b99f28d605d489a60cf - */ - - /* then change the needed ones */ - edata.cmd = ETHTOOL_SSET; - if (autoneg) { - edata.autoneg = AUTONEG_ENABLE; - if (!speed) - edata.advertising = edata.supported; - else { - guint32 mode; - - mode = get_baset_mode(speed, duplex); - - if (!mode) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised", - ifindex, - speed, - nm_platform_link_duplex_type_to_string(duplex)); - return FALSE; - } - if (!(edata.supported & mode)) { - nm_log_trace(LOGD_PLATFORM, - "ethtool[%d]: device does not support %uBASE-T %s duplex mode", - ifindex, - speed, - nm_platform_link_duplex_type_to_string(duplex)); - return FALSE; - } - edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode; - } - } else { - edata.autoneg = AUTONEG_DISABLE; - - if (speed) - ethtool_cmd_speed_set(&edata, speed); - - switch (duplex) { - case NM_PLATFORM_LINK_DUPLEX_HALF: - edata.duplex = DUPLEX_HALF; - break; - case NM_PLATFORM_LINK_DUPLEX_FULL: - edata.duplex = DUPLEX_FULL; - break; - case NM_PLATFORM_LINK_DUPLEX_UNKNOWN: - break; - default: - g_return_val_if_reached(FALSE); - } - } - - return _ethtool_call_handle(&shandle, &edata, sizeof(edata)) >= 0; -} - -gboolean -nmp_utils_ethtool_set_wake_on_lan(int ifindex, - NMSettingWiredWakeOnLan wol, - const char * wol_password) -{ - struct ethtool_wolinfo wol_info = { - .cmd = ETHTOOL_SWOL, - .wolopts = 0, - }; - - g_return_val_if_fail(ifindex > 0, FALSE); - - if (wol == NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE) - return TRUE; - - nm_log_dbg(LOGD_PLATFORM, - "ethtool[%d]: setting Wake-on-LAN options 0x%x, password '%s'", - ifindex, - (unsigned) wol, - wol_password); - - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY)) - wol_info.wolopts |= WAKE_PHY; - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST)) - wol_info.wolopts |= WAKE_UCAST; - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST)) - wol_info.wolopts |= WAKE_MCAST; - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST)) - wol_info.wolopts |= WAKE_BCAST; - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP)) - wol_info.wolopts |= WAKE_ARP; - if (NM_FLAGS_HAS(wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC)) - wol_info.wolopts |= WAKE_MAGIC; - - if (wol_password) { - if (!nm_utils_hwaddr_aton(wol_password, wol_info.sopass, ETH_ALEN)) { - nm_log_dbg(LOGD_PLATFORM, - "ethtool[%d]: couldn't parse Wake-on-LAN password '%s'", - ifindex, - wol_password); - return FALSE; - } - wol_info.wolopts |= WAKE_MAGICSECURE; - } - - return _ethtool_call_once(ifindex, &wol_info, sizeof(wol_info)) >= 0; -} - -/****************************************************************************** - * mii - *****************************************************************************/ - -gboolean -nmp_utils_mii_supports_carrier_detect(int ifindex) -{ - nm_auto_socket_handle SocketHandle shandle = SOCKET_HANDLE_INIT(ifindex); - int r; - struct ifreq ifr; - struct mii_ioctl_data * mii; - - g_return_val_if_fail(ifindex > 0, FALSE); - - r = _ioctl_call("mii", - "SIOCGMIIPHY", - SIOCGMIIPHY, - shandle.ifindex, - &shandle.fd, - shandle.ifname, - IOCTL_CALL_DATA_TYPE_NONE, - NULL, - 0, - &ifr); - if (r < 0) - return FALSE; - - /* If we can read the BMSR register, we assume that the card supports MII link detection */ - mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; - mii->reg_num = MII_BMSR; - - r = _ioctl_call("mii", - "SIOCGMIIREG", - SIOCGMIIREG, - shandle.ifindex, - &shandle.fd, - shandle.ifname, - IOCTL_CALL_DATA_TYPE_IFRU, - mii, - sizeof(*mii), - &ifr); - if (r < 0) - return FALSE; - - mii = (struct mii_ioctl_data *) &ifr.ifr_ifru; - nm_log_trace(LOGD_PLATFORM, - "mii[%d,%s]: carrier-detect yes: SIOCGMIIREG result 0x%X", - ifindex, - shandle.ifname, - mii->val_out); - return TRUE; -} - -/****************************************************************************** - * udev - *****************************************************************************/ - -const char * -nmp_utils_udev_get_driver(struct udev_device *udevice) -{ - struct udev_device *parent = NULL, *grandparent = NULL; - const char * driver, *subsys; - - driver = udev_device_get_driver(udevice); - if (driver) - goto out; - - /* Try the parent */ - parent = udev_device_get_parent(udevice); - if (parent) { - driver = udev_device_get_driver(parent); - if (!driver) { - /* Try the grandparent if it's an ibmebus device or if the - * subsys is NULL which usually indicates some sort of - * platform device like a 'gadget' net interface. - */ - subsys = udev_device_get_subsystem(parent); - if ((g_strcmp0(subsys, "ibmebus") == 0) || (subsys == NULL)) { - grandparent = udev_device_get_parent(parent); - if (grandparent) - driver = udev_device_get_driver(grandparent); - } - } - } - -out: - /* Intern the string so we don't have to worry about memory - * management in NMPlatformLink. */ - return g_intern_string(driver); -} - -/****************************************************************************** - * utils - *****************************************************************************/ - -NMIPConfigSource -nmp_utils_ip_config_source_from_rtprot(guint8 rtprot) -{ - return ((int) rtprot) + 1; -} - -NMIPConfigSource -nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source) -{ - /* when adding a route to kernel for a give @source, the resulting route - * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*. - * This function returns that. */ - return nmp_utils_ip_config_source_from_rtprot( - nmp_utils_ip_config_source_coerce_to_rtprot(source)); -} - -guint8 -nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source) -{ - /* when adding a route to kernel, we coerce the @source field - * to rtm_protocol. This is not lossless as we map different - * source values to the same RTPROT uint8 value. */ - if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN) - return RTPROT_UNSPEC; - - if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST) - return source - 1; - - switch (source) { - case NM_IP_CONFIG_SOURCE_KERNEL: - return RTPROT_KERNEL; - case NM_IP_CONFIG_SOURCE_IP6LL: - return RTPROT_KERNEL; - case NM_IP_CONFIG_SOURCE_DHCP: - return RTPROT_DHCP; - case NM_IP_CONFIG_SOURCE_NDISC: - return RTPROT_RA; - - default: - return RTPROT_STATIC; - } -} - -NMIPConfigSource -nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source) -{ - /* When we receive a route from kernel and put it into the platform cache, - * we preserve the protocol field by converting it to a NMIPConfigSource - * via nmp_utils_ip_config_source_from_rtprot(). - * - * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot(). - * Instead, to go back to the original value, you need another step: - * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)). - * - * This might partly restore the original source value, but of course that - * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot() - * is not injective. - * */ - switch (source) { - case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: - return NM_IP_CONFIG_SOURCE_UNKNOWN; - - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: - case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: - return NM_IP_CONFIG_SOURCE_KERNEL; - - case NM_IP_CONFIG_SOURCE_RTPROT_RA: - return NM_IP_CONFIG_SOURCE_NDISC; - - case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: - return NM_IP_CONFIG_SOURCE_DHCP; - - default: - return NM_IP_CONFIG_SOURCE_USER; - } -} - -const char * -nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len) -{ - const char *s = NULL; - nm_utils_to_string_buffer_init(&buf, &len); - - if (!len) - return buf; - - switch (source) { - case NM_IP_CONFIG_SOURCE_UNKNOWN: - s = "unknown"; - break; - - case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: - s = "rt-unspec"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: - s = "rt-redirect"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: - s = "rt-kernel"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_BOOT: - s = "rt-boot"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_STATIC: - s = "rt-static"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: - s = "rt-dhcp"; - break; - case NM_IP_CONFIG_SOURCE_RTPROT_RA: - s = "rt-ra"; - break; - - case NM_IP_CONFIG_SOURCE_KERNEL: - s = "kernel"; - break; - case NM_IP_CONFIG_SOURCE_SHARED: - s = "shared"; - break; - case NM_IP_CONFIG_SOURCE_IP4LL: - s = "ipv4ll"; - break; - case NM_IP_CONFIG_SOURCE_IP6LL: - s = "ipv6ll"; - break; - case NM_IP_CONFIG_SOURCE_PPP: - s = "ppp"; - break; - case NM_IP_CONFIG_SOURCE_WWAN: - s = "wwan"; - break; - case NM_IP_CONFIG_SOURCE_VPN: - s = "vpn"; - break; - case NM_IP_CONFIG_SOURCE_DHCP: - s = "dhcp"; - break; - case NM_IP_CONFIG_SOURCE_NDISC: - s = "ndisc"; - break; - case NM_IP_CONFIG_SOURCE_USER: - s = "user"; - break; - default: - break; - } - - if (source >= 1 && source <= 0x100) { - if (s) - g_snprintf(buf, len, "%s", s); - else - g_snprintf(buf, len, "rt-%d", ((int) source) - 1); - } else { - if (s) - g_strlcpy(buf, s, len); - else - g_snprintf(buf, len, "(%d)", source); - } - return buf; -} - -/** - * nmp_utils_sysctl_open_netdir: - * @ifindex: the ifindex for which to open "/sys/class/net/%s" - * @ifname_guess: (allow-none): optional argument, if present used as initial - * guess as the current name for @ifindex. If guessed right, - * it saves an additional if_indextoname() call. - * @out_ifname: (allow-none): if present, must be at least IFNAMSIZ - * characters. On success, this will contain the actual ifname - * found while opening the directory. - * - * Returns: a negative value on failure, on success returns the open fd - * to the "/sys/class/net/%s" directory for @ifindex. - */ -int -nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname) -{ -#define SYS_CLASS_NET "/sys/class/net/" - const char *ifname = ifname_guess; - char ifname_buf_last_try[IFNAMSIZ]; - char ifname_buf[IFNAMSIZ]; - guint try_count = 0; - char sysdir[NM_STRLEN(SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET; - char fd_buf[256]; - ssize_t nn; - - g_return_val_if_fail(ifindex >= 0, -1); - - ifname_buf_last_try[0] = '\0'; - - for (try_count = 0; try_count < 10; try_count++, ifname = NULL) { - nm_auto_close int fd_dir = -1; - nm_auto_close int fd_ifindex = -1; - - if (!ifname) { - ifname = nmp_utils_if_indextoname(ifindex, ifname_buf); - if (!ifname) - return -1; - } - - nm_assert(nm_utils_ifname_valid_kernel(ifname, NULL)); - - if (g_strlcpy(&sysdir[NM_STRLEN(SYS_CLASS_NET)], ifname, IFNAMSIZ) >= IFNAMSIZ) - g_return_val_if_reached(-1); - - /* we only retry, if the name changed since previous attempt. - * Hence, it is extremely unlikely that this loop runes until the - * end of the @try_count. */ - if (nm_streq(ifname, ifname_buf_last_try)) - return -1; - strcpy(ifname_buf_last_try, ifname); - - fd_dir = open(sysdir, O_DIRECTORY | O_CLOEXEC); - if (fd_dir < 0) - continue; - - fd_ifindex = openat(fd_dir, "ifindex", O_CLOEXEC); - if (fd_ifindex < 0) - continue; - - nn = nm_utils_fd_read_loop(fd_ifindex, fd_buf, sizeof(fd_buf) - 2, FALSE); - if (nn <= 0) - continue; - fd_buf[nn] = '\0'; - - if (ifindex != (int) _nm_utils_ascii_str_to_int64(fd_buf, 10, 1, G_MAXINT, -1)) - continue; - - if (out_ifname) - strcpy(out_ifname, ifname); - - return nm_steal_fd(&fd_dir); - } - - return -1; -} diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h deleted file mode 100644 index 076a2c7d..00000000 --- a/src/platform/nm-platform-utils.h +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2015 Red Hat, Inc. - */ - -#ifndef __NM_PLATFORM_UTILS_H__ -#define __NM_PLATFORM_UTILS_H__ - -#include "nm-platform.h" -#include "nm-setting-wired.h" -#include "nm-libnm-core-intern/nm-ethtool-utils.h" - -/*****************************************************************************/ - -const char *nmp_utils_ethtool_get_driver(int ifindex); -gboolean nmp_utils_ethtool_supports_carrier_detect(int ifindex); -gboolean nmp_utils_ethtool_supports_vlans(int ifindex); -int nmp_utils_ethtool_get_peer_ifindex(int ifindex); -gboolean nmp_utils_ethtool_get_wake_on_lan(int ifindex); -gboolean nmp_utils_ethtool_set_wake_on_lan(int ifindex, - NMSettingWiredWakeOnLan wol, - const char * wol_password); - -gboolean nmp_utils_ethtool_get_link_settings(int ifindex, - gboolean * out_autoneg, - guint32 * out_speed, - NMPlatformLinkDuplexType *out_duplex); -gboolean nmp_utils_ethtool_set_link_settings(int ifindex, - gboolean autoneg, - guint32 speed, - NMPlatformLinkDuplexType duplex); - -gboolean nmp_utils_ethtool_get_permanent_address(int ifindex, guint8 *buf, size_t *length); - -typedef struct { - /* We don't want to include <linux/ethtool.h> in header files, - * thus create a ABI compatible version of struct ethtool_drvinfo.*/ - guint32 _private_cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char _private_bus_info[32]; - char _private_erom_version[32]; - char _private_reserved2[12]; - guint32 _private_n_priv_flags; - guint32 _private_n_stats; - guint32 _private_testinfo_len; - guint32 _private_eedump_len; - guint32 _private_regdump_len; -} NMPUtilsEthtoolDriverInfo; - -gboolean nmp_utils_ethtool_get_driver_info(int ifindex, NMPUtilsEthtoolDriverInfo *data); - -typedef struct { - NMEthtoolID ethtool_id; - - guint8 n_kernel_names; - - /* one NMEthtoolID refers to one or more kernel_names. The reason for supporting this complexity - * (where one NMSettingEthtool option refers to multiple kernel features) is to follow what - * ethtool does, where "tx" is an alias for multiple features. */ - const char *const *kernel_names; -} NMEthtoolFeatureInfo; - -typedef struct { - const NMEthtoolFeatureInfo *info; - - guint idx_ss_features; - - /* one NMEthtoolFeatureInfo references one or more kernel_names. This is the index - * of the matching info->kernel_names */ - guint8 idx_kernel_name; - - bool available : 1; - bool requested : 1; - bool active : 1; - bool never_changed : 1; -} NMEthtoolFeatureState; - -struct _NMEthtoolFeatureStates { - guint n_states; - - guint n_ss_features; - - /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */ - const NMEthtoolFeatureState *const *states_indexed[_NM_ETHTOOL_ID_FEATURE_NUM]; - - /* the same content, here as a list of n_states entries. */ - const NMEthtoolFeatureState states_list[]; -}; - -NMEthtoolFeatureStates *nmp_utils_ethtool_get_features(int ifindex); - -gboolean nmp_utils_ethtool_set_features( - int ifindex, - const NMEthtoolFeatureStates *features, - const NMTernary *requested /* indexed by NMEthtoolID - _NM_ETHTOOL_ID_FEATURE_FIRST */, - gboolean do_set /* or reset */); - -struct _NMEthtoolCoalesceState { - guint32 - s[_NM_ETHTOOL_ID_COALESCE_NUM /* indexed by (NMEthtoolID - _NM_ETHTOOL_ID_COALESCE_FIRST) */ - ]; -}; - -gboolean nmp_utils_ethtool_get_coalesce(int ifindex, NMEthtoolCoalesceState *coalesce); - -gboolean nmp_utils_ethtool_set_coalesce(int ifindex, const NMEthtoolCoalesceState *coalesce); - -struct _NMEthtoolRingState { - guint32 rx_pending; - guint32 rx_mini_pending; - guint32 rx_jumbo_pending; - guint32 tx_pending; -}; - -gboolean nmp_utils_ethtool_get_ring(int ifindex, NMEthtoolRingState *ring); - -gboolean nmp_utils_ethtool_set_ring(int ifindex, const NMEthtoolRingState *ring); - -/*****************************************************************************/ - -gboolean nmp_utils_mii_supports_carrier_detect(int ifindex); - -struct udev_device; - -const char *nmp_utils_udev_get_driver(struct udev_device *udevice); - -NMIPConfigSource nmp_utils_ip_config_source_from_rtprot(guint8 rtprot) _nm_const; -guint8 nmp_utils_ip_config_source_coerce_to_rtprot(NMIPConfigSource source) _nm_const; -NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot(NMIPConfigSource source) _nm_const; -NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot(NMIPConfigSource source) _nm_const; -const char *nmp_utils_ip_config_source_to_string(NMIPConfigSource source, char *buf, gsize len); - -const char *nmp_utils_if_indextoname(int ifindex, char *out_ifname /*IFNAMSIZ*/); -int nmp_utils_if_nametoindex(const char *ifname); - -int nmp_utils_sysctl_open_netdir(int ifindex, const char *ifname_guess, char *out_ifname); - -#endif /* __NM_PLATFORM_UTILS_H__ */ diff --git a/src/platform/nmp-netns.c b/src/platform/nmp-netns.c deleted file mode 100644 index 07f7a7c9..00000000 --- a/src/platform/nmp-netns.c +++ /dev/null @@ -1,764 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2016 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nmp-netns.h" - -#include <fcntl.h> -#include <sys/mount.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <pthread.h> - -/*****************************************************************************/ - -/* NOTE: NMPNetns and all code used here must be thread-safe! */ - -/* we may not call logging functions from the main-thread alone. Hence, we - * require locking from nm-logging. Indicate that by setting NM_THREAD_SAFE_ON_MAIN_THREAD - * to zero. */ -#undef NM_THREAD_SAFE_ON_MAIN_THREAD -#define NM_THREAD_SAFE_ON_MAIN_THREAD 0 - -/*****************************************************************************/ - -#define PROC_SELF_NS_MNT "/proc/self/ns/mnt" -#define PROC_SELF_NS_NET "/proc/self/ns/net" - -#define _CLONE_NS_ALL ((int) (CLONE_NEWNS | CLONE_NEWNET)) -#define _CLONE_NS_ALL_V CLONE_NEWNS, CLONE_NEWNET - -static NM_UTILS_FLAGS2STR_DEFINE(_clone_ns_to_str, - int, - NM_UTILS_FLAGS2STR(CLONE_NEWNS, "mnt"), - NM_UTILS_FLAGS2STR(CLONE_NEWNET, "net"), ); - -static const char * -__ns_types_to_str(int ns_types, int ns_types_already_set, char *buf, gsize len) -{ - const char *b = buf; - char bb[200]; - - nm_utils_strbuf_append_c(&buf, &len, '['); - if (ns_types & ~ns_types_already_set) { - nm_utils_strbuf_append_str( - &buf, - &len, - _clone_ns_to_str(ns_types & ~ns_types_already_set, bb, sizeof(bb))); - } - if (ns_types & ns_types_already_set) { - if (ns_types & ~ns_types_already_set) - nm_utils_strbuf_append_c(&buf, &len, '/'); - nm_utils_strbuf_append_str( - &buf, - &len, - _clone_ns_to_str(ns_types & ns_types_already_set, bb, sizeof(bb))); - } - nm_utils_strbuf_append_c(&buf, &len, ']'); - return b; -} -#define _ns_types_to_str(ns_types, ns_types_already_set, buf) \ - __ns_types_to_str(ns_types, ns_types_already_set, buf, sizeof(buf)) - -/*****************************************************************************/ - -#define _NMLOG_DOMAIN LOGD_PLATFORM -#define _NMLOG_PREFIX_NAME "netns" -#define _NMLOG(level, netns, ...) \ - G_STMT_START \ - { \ - NMLogLevel _level = (level); \ - \ - if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ - NMPNetns *_netns = (netns); \ - char _sbuf[20]; \ - \ - _nm_log(_level, \ - _NMLOG_DOMAIN, \ - 0, \ - NULL, \ - NULL, \ - "%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (_netns ? nm_sprintf_buf(_sbuf, "[%p]", _netns) \ - : "") _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } \ - } \ - G_STMT_END - -/*****************************************************************************/ - -NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_FD_NET, PROP_FD_MNT, ); - -typedef struct { - int fd_net; - int fd_mnt; -} NMPNetnsPrivate; - -struct _NMPNetns { - GObject parent; - NMPNetnsPrivate _priv; -}; - -struct _NMPNetnsClass { - GObjectClass parent; -}; - -G_DEFINE_TYPE(NMPNetns, nmp_netns, G_TYPE_OBJECT); - -#define NMP_NETNS_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMPNetns, NMP_IS_NETNS) - -/*****************************************************************************/ - -typedef struct { - NMPNetns *netns; - int count; - int ns_types; -} NetnsInfo; - -static void _stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types); -static NMPNetns *_netns_new(GError **error); - -/*****************************************************************************/ - -static NMPNetns * -_netns_get(NetnsInfo *info) -{ - nm_assert(!info || NMP_IS_NETNS(info->netns)); - return info ? info->netns : NULL; -} - -/*****************************************************************************/ - -static _nm_thread_local GArray *_netns_stack = NULL; - -static void -_netns_stack_clear_cb(gpointer data) -{ - NetnsInfo *info = data; - - nm_assert(NMP_IS_NETNS(info->netns)); - g_object_unref(info->netns); -} - -static GArray * -_netns_stack_get_impl(void) -{ - gs_unref_object NMPNetns *netns = NULL; - gs_free_error GError *error = NULL; - pthread_key_t key; - GArray * s; - - s = g_array_new(FALSE, FALSE, sizeof(NetnsInfo)); - g_array_set_clear_func(s, _netns_stack_clear_cb); - _netns_stack = s; - - /* at the bottom of the stack we must try to create a netns instance - * that we never pop. It's the base to which we need to return. */ - netns = _netns_new(&error); - if (!netns) { - _LOGE(NULL, "failed to create initial netns: %s", error->message); - return s; - } - - /* we leak this instance inside the stack. */ - _stack_push(s, netns, _CLONE_NS_ALL); - - /* finally, register a destructor function to cleanup the array. If we fail - * to do so, we will leak NMPNetns instances (and their file descriptor) when the - * thread exits. */ - if (pthread_key_create(&key, (void (*)(void *)) g_array_unref) != 0) - _LOGE(NULL, "failure to initialize thread-local storage"); - else if (pthread_setspecific(key, s) != 0) - _LOGE(NULL, "failure to set thread-local storage"); - - return s; -} - -#define _netns_stack_get() \ - ({ \ - GArray *_s = _netns_stack; \ - \ - if (G_UNLIKELY(!_s)) \ - _s = _netns_stack_get_impl(); \ - _s; \ - }) - -/*****************************************************************************/ - -static NMPNetns * -_stack_current_netns(GArray *netns_stack, int ns_types) -{ - guint j; - - nm_assert(netns_stack && netns_stack->len > 0); - - /* we search the stack top-down to find the netns that has - * all @ns_types set. */ - for (j = netns_stack->len; ns_types && j >= 1;) { - NetnsInfo *info; - - info = &g_array_index(netns_stack, NetnsInfo, --j); - - if (NM_FLAGS_ALL(info->ns_types, ns_types)) - return info->netns; - } - - g_return_val_if_reached(NULL); -} - -static int -_stack_current_ns_types(GArray *netns_stack, NMPNetns *netns, int ns_types) -{ - const int ns_types_check[] = {_CLONE_NS_ALL_V}; - guint i, j; - int res = 0; - - nm_assert(netns); - nm_assert(netns_stack && netns_stack->len > 0); - - /* we search the stack top-down to check which of @ns_types - * are already set to @netns. */ - for (j = netns_stack->len; ns_types && j >= 1;) { - NetnsInfo *info; - - info = &g_array_index(netns_stack, NetnsInfo, --j); - if (info->netns != netns) { - ns_types = NM_FLAGS_UNSET(ns_types, info->ns_types); - continue; - } - - for (i = 0; i < G_N_ELEMENTS(ns_types_check); i++) { - if (NM_FLAGS_ANY(ns_types, ns_types_check[i]) - && NM_FLAGS_ANY(info->ns_types, ns_types_check[i])) { - res = NM_FLAGS_SET(res, ns_types_check[i]); - ns_types = NM_FLAGS_UNSET(ns_types, ns_types_check[i]); - } - } - } - - return res; -} - -static NetnsInfo * -_stack_peek(GArray *netns_stack) -{ - if (netns_stack->len > 0) - return &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); - return NULL; -} - -static NetnsInfo * -_stack_bottom(GArray *netns_stack) -{ - if (netns_stack->len > 0) - return &g_array_index(netns_stack, NetnsInfo, 0); - return NULL; -} - -static void -_stack_push(GArray *netns_stack, NMPNetns *netns, int ns_types) -{ - NetnsInfo *info; - - nm_assert(netns_stack); - nm_assert(NMP_IS_NETNS(netns)); - nm_assert(NM_FLAGS_ANY(ns_types, _CLONE_NS_ALL)); - nm_assert(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL)); - - g_array_set_size(netns_stack, netns_stack->len + 1); - - info = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); - *info = (NetnsInfo){ - .netns = g_object_ref(netns), - .ns_types = ns_types, - .count = 1, - }; -} - -static void -_stack_pop(GArray *netns_stack) -{ - NetnsInfo *info; - - nm_assert(netns_stack); - nm_assert(netns_stack->len > 1); - - info = &g_array_index(netns_stack, NetnsInfo, (netns_stack->len - 1)); - - nm_assert(NMP_IS_NETNS(info->netns)); - nm_assert(info->count == 1); - - g_array_set_size(netns_stack, netns_stack->len - 1); -} - -static guint -_stack_size(GArray *netns_stack) -{ - nm_assert(netns_stack); - - return netns_stack->len; -} - -/*****************************************************************************/ - -static NMPNetns * -_netns_new(GError **error) -{ - NMPNetns *self; - int fd_net, fd_mnt; - int errsv; - - fd_net = open(PROC_SELF_NS_NET, O_RDONLY | O_CLOEXEC); - if (fd_net == -1) { - errsv = errno; - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "Failed opening netns: %s", - nm_strerror_native(errsv)); - errno = errsv; - return NULL; - } - - fd_mnt = open(PROC_SELF_NS_MNT, O_RDONLY | O_CLOEXEC); - if (fd_mnt == -1) { - errsv = errno; - g_set_error(error, - NM_UTILS_ERROR, - NM_UTILS_ERROR_UNKNOWN, - "Failed opening mntns: %s", - nm_strerror_native(errsv)); - nm_close(fd_net); - errno = errsv; - return NULL; - } - - self = g_object_new(NMP_TYPE_NETNS, NMP_NETNS_FD_NET, fd_net, NMP_NETNS_FD_MNT, fd_mnt, NULL); - - _LOGD(self, "new netns (net:%d, mnt:%d)", fd_net, fd_mnt); - - return self; -} - -static int -_setns(NMPNetns *self, int type) -{ - char buf[100]; - int fd; - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); - - nm_assert(NM_IN_SET(type, _CLONE_NS_ALL_V)); - - fd = (type == CLONE_NEWNET) ? priv->fd_net : priv->fd_mnt; - - _LOGt(self, "set netns(%s, %d)", _ns_types_to_str(type, 0, buf), fd); - - return setns(fd, type); -} - -static gboolean -_netns_switch_push(GArray *netns_stack, NMPNetns *self, int ns_types) -{ - int errsv; - - if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) - && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET) - && _setns(self, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv)); - return FALSE; - } - if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS) - && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS) - && _setns(self, CLONE_NEWNS) != 0) { - errsv = errno; - _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv)); - - /* try to fix the mess by returning to the previous netns. */ - if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) - && !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET)) { - self = _stack_current_netns(netns_stack, CLONE_NEWNET); - if (self && _setns(self, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE(self, "failed to restore netns: %s", nm_strerror_native(errsv)); - } - } - return FALSE; - } - - return TRUE; -} - -static gboolean -_netns_switch_pop(GArray *netns_stack, NMPNetns *self, int ns_types) -{ - int errsv; - NMPNetns *current; - int success = TRUE; - - if (NM_FLAGS_HAS(ns_types, CLONE_NEWNET) - && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNET))) { - current = _stack_current_netns(netns_stack, CLONE_NEWNET); - if (!current) { - g_warn_if_reached(); - success = FALSE; - } else if (_setns(current, CLONE_NEWNET) != 0) { - errsv = errno; - _LOGE(self, "failed to switch netns: %s", nm_strerror_native(errsv)); - success = FALSE; - } - } - if (NM_FLAGS_HAS(ns_types, CLONE_NEWNS) - && (!self || !_stack_current_ns_types(netns_stack, self, CLONE_NEWNS))) { - current = _stack_current_netns(netns_stack, CLONE_NEWNS); - if (!current) { - g_warn_if_reached(); - success = FALSE; - } else if (_setns(current, CLONE_NEWNS) != 0) { - errsv = errno; - _LOGE(self, "failed to switch mntns: %s", nm_strerror_native(errsv)); - success = FALSE; - } - } - - return success; -} - -/*****************************************************************************/ - -int -nmp_netns_get_fd_net(NMPNetns *self) -{ - g_return_val_if_fail(NMP_IS_NETNS(self), 0); - - return NMP_NETNS_GET_PRIVATE(self)->fd_net; -} - -int -nmp_netns_get_fd_mnt(NMPNetns *self) -{ - g_return_val_if_fail(NMP_IS_NETNS(self), 0); - - return NMP_NETNS_GET_PRIVATE(self)->fd_mnt; -} - -/*****************************************************************************/ - -static gboolean -_nmp_netns_push_type(NMPNetns *self, int ns_types) -{ - GArray * netns_stack = _netns_stack_get(); - NetnsInfo *info; - char sbuf[100]; - - info = _stack_peek(netns_stack); - g_return_val_if_fail(info, FALSE); - - if (info->netns == self && info->ns_types == ns_types) { - info->count++; - _LOGt(self, - "push#%u* %s (increase count to %d)", - _stack_size(netns_stack) - 1, - _ns_types_to_str(ns_types, ns_types, sbuf), - info->count); - return TRUE; - } - - _LOGD(self, - "push#%u %s", - _stack_size(netns_stack), - _ns_types_to_str(ns_types, _stack_current_ns_types(netns_stack, self, ns_types), sbuf)); - - if (!_netns_switch_push(netns_stack, self, ns_types)) - return FALSE; - - _stack_push(netns_stack, self, ns_types); - return TRUE; -} - -gboolean -nmp_netns_push(NMPNetns *self) -{ - g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - - return _nmp_netns_push_type(self, _CLONE_NS_ALL); -} - -gboolean -nmp_netns_push_type(NMPNetns *self, int ns_types) -{ - g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - g_return_val_if_fail(!NM_FLAGS_ANY(ns_types, ~_CLONE_NS_ALL), FALSE); - - return _nmp_netns_push_type(self, ns_types == 0 ? _CLONE_NS_ALL : ns_types); -} - -NMPNetns * -nmp_netns_new(void) -{ - GArray * netns_stack = _netns_stack_get(); - NMPNetns * self; - int errsv; - GError * error = NULL; - unsigned long mountflags = 0; - - if (!_stack_peek(netns_stack)) { - /* there are no netns instances. We cannot create a new one - * (because after unshare we couldn't return to the original one). */ - errno = ENOTSUP; - return NULL; - } - - if (unshare(_CLONE_NS_ALL) != 0) { - errsv = errno; - _LOGE(NULL, "failed to create new net and mnt namespace: %s", nm_strerror_native(errsv)); - return NULL; - } - - if (mount("", "/", "none", MS_SLAVE | MS_REC, NULL) != 0) { - errsv = errno; - _LOGE(NULL, "failed mount --make-rslave: %s", nm_strerror_native(errsv)); - goto err_out; - } - - if (umount2("/sys", MNT_DETACH) != 0) { - errsv = errno; - _LOGE(NULL, "failed umount /sys: %s", nm_strerror_native(errsv)); - goto err_out; - } - - if (access("/sys", W_OK) == -1) - mountflags = MS_RDONLY; - - if (mount("sysfs", "/sys", "sysfs", mountflags, NULL) != 0) { - errsv = errno; - _LOGE(NULL, "failed mount /sys: %s", nm_strerror_native(errsv)); - goto err_out; - } - - self = _netns_new(&error); - if (!self) { - errsv = errno; - _LOGE(NULL, "failed to create netns after unshare: %s", error->message); - g_clear_error(&error); - goto err_out; - } - - _stack_push(netns_stack, self, _CLONE_NS_ALL); - - return self; -err_out: - _netns_switch_pop(netns_stack, NULL, _CLONE_NS_ALL); - errno = errsv; - return NULL; -} - -gboolean -nmp_netns_pop(NMPNetns *self) -{ - GArray * netns_stack = _netns_stack_get(); - NetnsInfo *info; - int ns_types; - - g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - - info = _stack_peek(netns_stack); - - g_return_val_if_fail(info, FALSE); - g_return_val_if_fail(info->netns == self, FALSE); - - if (info->count > 1) { - info->count--; - _LOGt(self, "pop#%u* (decrease count to %d)", _stack_size(netns_stack) - 1, info->count); - return TRUE; - } - g_return_val_if_fail(info->count == 1, FALSE); - - /* cannot pop the original netns. */ - g_return_val_if_fail(_stack_size(netns_stack) > 1, FALSE); - - _LOGD(self, "pop#%u", _stack_size(netns_stack) - 1); - - ns_types = info->ns_types; - - _stack_pop(netns_stack); - - return _netns_switch_pop(netns_stack, self, ns_types); -} - -NMPNetns * -nmp_netns_get_current(void) -{ - return _netns_get(_stack_peek(_netns_stack_get())); -} - -NMPNetns * -nmp_netns_get_initial(void) -{ - return _netns_get(_stack_bottom(_netns_stack_get())); -} - -gboolean -nmp_netns_is_initial(void) -{ - GArray *netns_stack = _netns_stack_get(); - - return (_netns_get(_stack_peek(netns_stack)) == _netns_get(_stack_bottom(netns_stack))); -} - -/*****************************************************************************/ - -gboolean -nmp_netns_bind_to_path(NMPNetns *self, const char *filename, int *out_fd) -{ - gs_free char * dirname = NULL; - int errsv; - int fd; - nm_auto_pop_netns NMPNetns *netns_pop = NULL; - - g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - g_return_val_if_fail(filename && filename[0] == '/', FALSE); - - if (!nmp_netns_push_type(self, CLONE_NEWNET)) - return FALSE; - netns_pop = self; - - dirname = g_path_get_dirname(filename); - if (mkdir(dirname, 0) != 0) { - errsv = errno; - if (errsv != EEXIST) { - _LOGE(self, - "bind: failed to create directory %s: %s", - dirname, - nm_strerror_native(errsv)); - return FALSE; - } - } - - if ((fd = creat(filename, S_IRUSR | S_IRGRP | S_IROTH)) == -1) { - errsv = errno; - _LOGE(self, "bind: failed to create %s: %s", filename, nm_strerror_native(errsv)); - return FALSE; - } - nm_close(fd); - - if (mount(PROC_SELF_NS_NET, filename, "none", MS_BIND, NULL) != 0) { - errsv = errno; - _LOGE(self, - "bind: failed to mount %s to %s: %s", - PROC_SELF_NS_NET, - filename, - nm_strerror_native(errsv)); - unlink(filename); - return FALSE; - } - - if (out_fd) { - if ((fd = open(filename, O_RDONLY | O_CLOEXEC)) == -1) { - errsv = errno; - _LOGE(self, "bind: failed to open %s: %s", filename, nm_strerror_native(errsv)); - umount2(filename, MNT_DETACH); - unlink(filename); - return FALSE; - } - *out_fd = fd; - } - - return TRUE; -} - -gboolean -nmp_netns_bind_to_path_destroy(NMPNetns *self, const char *filename) -{ - int errsv; - - g_return_val_if_fail(NMP_IS_NETNS(self), FALSE); - g_return_val_if_fail(filename && filename[0] == '/', FALSE); - - if (umount2(filename, MNT_DETACH) != 0) { - errsv = errno; - _LOGE(self, "bind: failed to unmount2 %s: %s", filename, nm_strerror_native(errsv)); - return FALSE; - } - if (unlink(filename) != 0) { - errsv = errno; - _LOGE(self, "bind: failed to unlink %s: %s", filename, nm_strerror_native(errsv)); - return FALSE; - } - return TRUE; -} - -/*****************************************************************************/ - -static void -set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - NMPNetns * self = NMP_NETNS(object); - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); - - switch (prop_id) { - case PROP_FD_NET: - /* construct-only */ - priv->fd_net = g_value_get_int(value); - g_return_if_fail(priv->fd_net > 0); - break; - case PROP_FD_MNT: - /* construct-only */ - priv->fd_mnt = g_value_get_int(value); - g_return_if_fail(priv->fd_mnt > 0); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -nmp_netns_init(NMPNetns *self) -{} - -static void -dispose(GObject *object) -{ - NMPNetns * self = NMP_NETNS(object); - NMPNetnsPrivate *priv = NMP_NETNS_GET_PRIVATE(self); - - nm_close(priv->fd_net); - priv->fd_net = -1; - - nm_close(priv->fd_mnt); - priv->fd_mnt = -1; - - G_OBJECT_CLASS(nmp_netns_parent_class)->dispose(object); -} - -static void -nmp_netns_class_init(NMPNetnsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS(klass); - - object_class->set_property = set_property; - object_class->dispose = dispose; - - obj_properties[PROP_FD_NET] = - g_param_spec_int(NMP_NETNS_FD_NET, - "", - "", - 0, - G_MAXINT, - 0, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - obj_properties[PROP_FD_MNT] = - g_param_spec_int(NMP_NETNS_FD_MNT, - "", - "", - 0, - G_MAXINT, - 0, - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); - g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties); -} diff --git a/src/platform/nmp-netns.h b/src/platform/nmp-netns.h deleted file mode 100644 index 2516a79e..00000000 --- a/src/platform/nmp-netns.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * Copyright (C) 2016 Red Hat, Inc. - */ - -#ifndef __NMP_NETNS_UTILS_H__ -#define __NMP_NETNS_UTILS_H__ - -/*****************************************************************************/ - -#define NMP_TYPE_NETNS (nmp_netns_get_type()) -#define NMP_NETNS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NMP_TYPE_NETNS, NMPNetns)) -#define NMP_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), NMP_TYPE_NETNS, NMPNetnsClass)) -#define NMP_IS_NETNS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NMP_TYPE_NETNS)) -#define NMP_IS_NETNS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NMP_TYPE_NETNS)) -#define NMP_NETNS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), NMP_TYPE_NETNS, NMPNetnsClass)) - -#define NMP_NETNS_FD_NET "fd-net" -#define NMP_NETNS_FD_MNT "fd-mnt" - -typedef struct _NMPNetnsClass NMPNetnsClass; - -GType nmp_netns_get_type(void); - -NMPNetns *nmp_netns_new(void); - -gboolean nmp_netns_push(NMPNetns *self); -gboolean nmp_netns_push_type(NMPNetns *self, int ns_types); -gboolean nmp_netns_pop(NMPNetns *self); - -NMPNetns *nmp_netns_get_current(void); -NMPNetns *nmp_netns_get_initial(void); -gboolean nmp_netns_is_initial(void); - -int nmp_netns_get_fd_net(NMPNetns *self); -int nmp_netns_get_fd_mnt(NMPNetns *self); - -static inline void -_nm_auto_pop_netns(NMPNetns **p) -{ - if (*p) { - int errsv = errno; - - nmp_netns_pop(*p); - errno = errsv; - } -} -#define nm_auto_pop_netns nm_auto(_nm_auto_pop_netns) - -gboolean nmp_netns_bind_to_path(NMPNetns *self, const char *filename, int *out_fd); -gboolean nmp_netns_bind_to_path_destroy(NMPNetns *self, const char *filename); - -#endif /* __NMP_NETNS_UTILS_H__ */ diff --git a/src/settings/plugins/ifcfg-rh/tests/meson.build b/src/settings/plugins/ifcfg-rh/tests/meson.build deleted file mode 100644 index 1ce61c90..00000000 --- a/src/settings/plugins/ifcfg-rh/tests/meson.build +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -test_unit = 'test-ifcfg-rh' - -exe = executable( - test_unit, - test_unit + '.c', - dependencies: libnetwork_manager_test_dep, - c_args: test_c_flags, - link_with: libnms_ifcfg_rh_core, -) - -test( - 'ifcfg-rh/' + test_unit, - test_script, - timeout: 90, - args: test_args + [exe.full_path()], -) diff --git a/src/settings/plugins/ifupdown/tests/meson.build b/src/settings/plugins/ifupdown/tests/meson.build deleted file mode 100644 index a39e4e21..00000000 --- a/src/settings/plugins/ifupdown/tests/meson.build +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -test_unit = 'test-ifupdown' - -exe = executable( - test_unit, - test_unit + '.c', - dependencies: libnetwork_manager_test_dep, - c_args: test_c_flags, - link_with: libnms_ifupdown_core, -) - -test( - 'ifupdown/' + test_unit, - test_script, - args: test_args + [exe.full_path()], -) diff --git a/src/settings/plugins/keyfile/tests/meson.build b/src/settings/plugins/keyfile/tests/meson.build deleted file mode 100644 index cd1dc3aa..00000000 --- a/src/settings/plugins/keyfile/tests/meson.build +++ /dev/null @@ -1,17 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -test_unit = 'test-keyfile-settings' - -exe = executable( - test_unit, - test_unit + '.c', - dependencies: libnetwork_manager_test_dep, - c_args: test_c_flags, -) - -test( - test_unit, - test_script, - args: test_args + [exe.full_path()], - timeout: default_test_timeout, -) diff --git a/src/systemd/meson.build b/src/systemd/meson.build deleted file mode 100644 index 9b87d772..00000000 --- a/src/systemd/meson.build +++ /dev/null @@ -1,50 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1+ - -sources = files( - 'src/libsystemd-network/arp-util.c', - 'src/libsystemd-network/dhcp-identifier.c', - 'src/libsystemd-network/dhcp-network.c', - 'src/libsystemd-network/dhcp-option.c', - 'src/libsystemd-network/dhcp-packet.c', - 'src/libsystemd-network/dhcp6-network.c', - 'src/libsystemd-network/dhcp6-option.c', - 'src/libsystemd-network/lldp-neighbor.c', - 'src/libsystemd-network/lldp-network.c', - 'src/libsystemd-network/network-internal.c', - 'src/libsystemd-network/sd-dhcp-client.c', - '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', - 'src/libsystemd/sd-id128/id128-util.c', - 'src/libsystemd/sd-id128/sd-id128.c', - 'nm-sd.c', - 'nm-sd-utils-core.c', - 'nm-sd-utils-dhcp.c', - 'sd-adapt-core/nm-sd-adapt-core.c', -) - -incs = include_directories( - 'sd-adapt-core', - 'src/libsystemd-network', - 'src/libsystemd/sd-event', - 'src/systemd', -) - -deps = [ - daemon_nm_default_dep, - libnm_systemd_shared_dep, -] - -libnm_systemd_core = static_library( - 'nm-systemd-core', - sources: sources, - include_directories: incs, - dependencies: deps, - c_args: '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_SYSTEMD', - link_with: libc_siphash, -) diff --git a/src/systemd/src/libsystemd-network/network-internal.c b/src/systemd/src/libsystemd-network/network-internal.c deleted file mode 100644 index 6a7382ac..00000000 --- a/src/systemd/src/libsystemd-network/network-internal.c +++ /dev/null @@ -1,890 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ - -#include "nm-sd-adapt-core.h" - -#include <arpa/inet.h> -#include <linux/if.h> -#include <netinet/ether.h> - -#include "sd-id128.h" -#include "sd-ndisc.h" - -#include "alloc-util.h" -#include "arphrd-list.h" -#include "condition.h" -#include "conf-parser.h" -#include "device-util.h" -#include "dhcp-lease-internal.h" -#include "env-util.h" -#include "ether-addr-util.h" -#include "hexdecoct.h" -#include "log.h" -#include "network-internal.h" -#include "parse-util.h" -#include "siphash24.h" -#include "socket-util.h" -#include "string-table.h" -#include "string-util.h" -#include "strv.h" -#include "utf8.h" -#include "util.h" - -#if 0 /* NM_IGNORED */ -const char *net_get_name_persistent(sd_device *device) { - const char *name, *field; - - assert(device); - - /* fetch some persistent data unique (on this machine) to this device */ - FOREACH_STRING(field, "ID_NET_NAME_ONBOARD", "ID_NET_NAME_SLOT", "ID_NET_NAME_PATH", "ID_NET_NAME_MAC") - if (sd_device_get_property_value(device, field, &name) >= 0) - return name; - - return NULL; -} - -#define HASH_KEY SD_ID128_MAKE(d3,1e,48,fa,90,fe,4b,4c,9d,af,d5,d7,a1,b1,2e,8a) - -int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result) { - size_t l, sz = 0; - const char *name; - int r; - uint8_t *v; - - assert(device); - - /* net_get_name_persistent() will return one of the device names based on stable information about - * the device. If this is not available, we fall back to using the actual device name. */ - name = net_get_name_persistent(device); - if (!name && use_sysname) - (void) sd_device_get_sysname(device, &name); - if (!name) - return log_device_debug_errno(device, SYNTHETIC_ERRNO(ENODATA), - "No stable identifying information found"); - - log_device_debug(device, "Using \"%s\" as stable identifying information", name); - l = strlen(name); - sz = sizeof(sd_id128_t) + l; - v = newa(uint8_t, sz); - - /* Fetch some persistent data unique to this machine */ - r = sd_id128_get_machine((sd_id128_t*) v); - if (r < 0) - return r; - memcpy(v + sizeof(sd_id128_t), name, l); - - /* Let's hash the machine ID plus the device name. We use - * a fixed, but originally randomly created hash key here. */ - *result = htole64(siphash24(v, sz, HASH_KEY.bytes)); - return 0; -} - -static bool net_condition_test_strv(char * const *patterns, const char *string) { - char * const *p; - bool match = false, has_positive_rule = false; - - if (strv_isempty(patterns)) - return true; - - STRV_FOREACH(p, patterns) { - const char *q = *p; - bool invert; - - invert = *q == '!'; - q += invert; - - if (!invert) - has_positive_rule = true; - - if (string && fnmatch(q, string, 0) == 0) { - if (invert) - return false; - else - match = true; - } - } - - return has_positive_rule ? match : true; -} - -static bool net_condition_test_ifname(char * const *patterns, const char *ifname, char * const *alternative_names) { - if (net_condition_test_strv(patterns, ifname)) - return true; - - char * const *p; - STRV_FOREACH(p, alternative_names) - if (net_condition_test_strv(patterns, *p)) - return true; - - return false; -} - -static int net_condition_test_property(char * const *match_property, sd_device *device) { - char * const *p; - - if (strv_isempty(match_property)) - return true; - - STRV_FOREACH(p, match_property) { - _cleanup_free_ char *key = NULL; - const char *val, *dev_val; - bool invert, v; - - invert = **p == '!'; - - val = strchr(*p + invert, '='); - if (!val) - return -EINVAL; - - key = strndup(*p + invert, val - *p - invert); - if (!key) - return -ENOMEM; - - val++; - - v = device && - sd_device_get_property_value(device, key, &dev_val) >= 0 && - fnmatch(val, dev_val, 0) == 0; - - if (invert ? v : !v) - return false; - } - - return true; -} - -static const char *const wifi_iftype_table[NL80211_IFTYPE_MAX+1] = { - [NL80211_IFTYPE_ADHOC] = "ad-hoc", - [NL80211_IFTYPE_STATION] = "station", - [NL80211_IFTYPE_AP] = "ap", - [NL80211_IFTYPE_AP_VLAN] = "ap-vlan", - [NL80211_IFTYPE_WDS] = "wds", - [NL80211_IFTYPE_MONITOR] = "monitor", - [NL80211_IFTYPE_MESH_POINT] = "mesh-point", - [NL80211_IFTYPE_P2P_CLIENT] = "p2p-client", - [NL80211_IFTYPE_P2P_GO] = "p2p-go", - [NL80211_IFTYPE_P2P_DEVICE] = "p2p-device", - [NL80211_IFTYPE_OCB] = "ocb", - [NL80211_IFTYPE_NAN] = "nan", -}; - -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(wifi_iftype, enum nl80211_iftype); - -char *link_get_type_string(unsigned short iftype, sd_device *device) { - const char *t, *devtype; - char *p; - - if (device && - sd_device_get_devtype(device, &devtype) >= 0 && - !isempty(devtype)) - return strdup(devtype); - - t = arphrd_to_name(iftype); - if (!t) - return NULL; - - p = strdup(t); - if (!p) - return NULL; - - ascii_strlower(p); - return p; -} - -bool net_match_config(Set *match_mac, - Set *match_permanent_mac, - char * const *match_paths, - char * const *match_drivers, - char * const *match_iftypes, - char * const *match_names, - char * const *match_property, - char * const *match_wifi_iftype, - char * const *match_ssid, - Set *match_bssid, - sd_device *device, - const struct ether_addr *dev_mac, - const struct ether_addr *dev_permanent_mac, - const char *dev_driver, - unsigned short dev_iftype, - const char *dev_name, - char * const *alternative_names, - enum nl80211_iftype dev_wifi_iftype, - const char *dev_ssid, - const struct ether_addr *dev_bssid) { - - _cleanup_free_ char *dev_iftype_str; - const char *dev_path = NULL; - - dev_iftype_str = link_get_type_string(dev_iftype, device); - - if (device) { - const char *mac_str; - - (void) sd_device_get_property_value(device, "ID_PATH", &dev_path); - if (!dev_driver) - (void) sd_device_get_property_value(device, "ID_NET_DRIVER", &dev_driver); - if (!dev_name) - (void) sd_device_get_sysname(device, &dev_name); - if (!dev_mac && - sd_device_get_sysattr_value(device, "address", &mac_str) >= 0) - dev_mac = ether_aton(mac_str); - } - - if (match_mac && (!dev_mac || !set_contains(match_mac, dev_mac))) - return false; - - if (match_permanent_mac && - (!dev_permanent_mac || - ether_addr_is_null(dev_permanent_mac) || - !set_contains(match_permanent_mac, dev_permanent_mac))) - return false; - - if (!net_condition_test_strv(match_paths, dev_path)) - return false; - - if (!net_condition_test_strv(match_drivers, dev_driver)) - return false; - - if (!net_condition_test_strv(match_iftypes, dev_iftype_str)) - return false; - - if (!net_condition_test_ifname(match_names, dev_name, alternative_names)) - return false; - - if (!net_condition_test_property(match_property, device)) - return false; - - if (!net_condition_test_strv(match_wifi_iftype, wifi_iftype_to_string(dev_wifi_iftype))) - return false; - - if (!net_condition_test_strv(match_ssid, dev_ssid)) - return false; - - if (match_bssid && (!dev_bssid || !set_contains(match_bssid, dev_bssid))) - return false; - - return true; -} - -int config_parse_net_condition(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - ConditionType cond = ltype; - Condition **list = data, *c; - bool negate; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - *list = condition_free_list_type(*list, cond); - return 0; - } - - negate = rvalue[0] == '!'; - if (negate) - rvalue++; - - c = condition_new(cond, rvalue, false, negate); - if (!c) - return log_oom(); - - /* Drop previous assignment. */ - *list = condition_free_list_type(*list, cond); - - LIST_PREPEND(conditions, *list, c); - return 0; -} - -int config_parse_match_strv( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - const char *p = rvalue; - char ***sv = data; - bool invert; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - *sv = strv_free(*sv); - return 0; - } - - invert = *p == '!'; - p += invert; - - for (;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE|EXTRACT_RETAIN_ESCAPE); - if (r == 0) - return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); - return 0; - } - - if (invert) { - k = strjoin("!", word); - if (!k) - return log_oom(); - } else - k = TAKE_PTR(word); - - r = strv_consume(sv, TAKE_PTR(k)); - if (r < 0) - return log_oom(); - } -} - -int config_parse_match_ifnames( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - const char *p = rvalue; - char ***sv = data; - bool invert; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - invert = *p == '!'; - p += invert; - - for (;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) - return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Failed to parse interface name list: %s", rvalue); - return 0; - } - - if (!ifname_valid_full(word, ltype)) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Interface name is not valid or too long, ignoring assignment: %s", word); - continue; - } - - if (invert) { - k = strjoin("!", word); - if (!k) - return log_oom(); - } else - k = TAKE_PTR(word); - - r = strv_consume(sv, TAKE_PTR(k)); - if (r < 0) - return log_oom(); - } -} - -int config_parse_match_property( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - const char *p = rvalue; - char ***sv = data; - bool invert; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - invert = *p == '!'; - p += invert; - - for (;;) { - _cleanup_free_ char *word = NULL, *k = NULL; - - r = extract_first_word(&p, &word, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE); - if (r == 0) - return 0; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Invalid syntax, ignoring: %s", rvalue); - return 0; - } - - if (!env_assignment_is_valid(word)) { - log_syntax(unit, LOG_ERR, filename, line, 0, - "Invalid property or value, ignoring assignment: %s", word); - continue; - } - - if (invert) { - k = strjoin("!", word); - if (!k) - return log_oom(); - } else - k = TAKE_PTR(word); - - r = strv_consume(sv, TAKE_PTR(k)); - if (r < 0) - return log_oom(); - } -} - -int config_parse_ifalias(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - char **s = data; - _cleanup_free_ char *n = NULL; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - n = strdup(rvalue); - if (!n) - return log_oom(); - - if (!ascii_is_valid(n) || strlen(n) >= IFALIASZ) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Interface alias is not ASCII clean or is too long, ignoring assignment: %s", rvalue); - return 0; - } - - if (isempty(n)) - *s = mfree(*s); - else - free_and_replace(*s, n); - - return 0; -} - -int config_parse_hwaddr(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - _cleanup_free_ struct ether_addr *n = NULL; - struct ether_addr **hwaddr = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - n = new0(struct ether_addr, 1); - if (!n) - return log_oom(); - - r = ether_addr_from_string(rvalue, n); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Not a valid MAC address, ignoring assignment: %s", rvalue); - return 0; - } - - free_and_replace(*hwaddr, n); - - return 0; -} - -int config_parse_hwaddrs(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - _cleanup_set_free_free_ Set *s = NULL; - const char *p = rvalue; - Set **hwaddrs = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (isempty(rvalue)) { - /* Empty assignment resets the list */ - *hwaddrs = set_free_free(*hwaddrs); - return 0; - } - - s = set_new(ðer_addr_hash_ops); - if (!s) - return log_oom(); - - for (;;) { - _cleanup_free_ char *word = NULL; - _cleanup_free_ struct ether_addr *n = NULL; - - r = extract_first_word(&p, &word, NULL, 0); - if (r == 0) - break; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); - return 0; - } - - n = new(struct ether_addr, 1); - if (!n) - return log_oom(); - - r = ether_addr_from_string(word, n); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring: %s", word); - continue; - } - - r = set_put(s, n); - if (r < 0) - return log_oom(); - if (r > 0) - n = NULL; /* avoid cleanup */ - } - - r = set_ensure_allocated(hwaddrs, ðer_addr_hash_ops); - if (r < 0) - return log_oom(); - - r = set_move(*hwaddrs, s); - if (r < 0) - return log_oom(); - - return 0; -} - -int config_parse_bridge_port_priority( - const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { - - uint16_t i; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = safe_atou16(rvalue, &i); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse bridge port priority, ignoring: %s", rvalue); - return 0; - } - - if (i > LINK_BRIDGE_PORT_PRIORITY_MAX) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Bridge port priority is larger than maximum %u, ignoring: %s", LINK_BRIDGE_PORT_PRIORITY_MAX, rvalue); - return 0; - } - - *((uint16_t *)data) = i; - - return 0; -} -#endif /* NM_IGNORED */ - -size_t serialize_in_addrs(FILE *f, - const struct in_addr *addresses, - size_t size, - bool *with_leading_space, - bool (*predicate)(const struct in_addr *addr)) { - assert(f); - assert(addresses); - - size_t count = 0; - bool _space = false; - if (!with_leading_space) - with_leading_space = &_space; - - for (size_t i = 0; i < size; i++) { - char sbuf[INET_ADDRSTRLEN]; - - if (predicate && !predicate(&addresses[i])) - continue; - - if (*with_leading_space) - fputc(' ', f); - fputs(inet_ntop(AF_INET, &addresses[i], sbuf, sizeof(sbuf)), f); - count++; - *with_leading_space = true; - } - - return count; -} - -int deserialize_in_addrs(struct in_addr **ret, const char *string) { - _cleanup_free_ struct in_addr *addresses = NULL; - int size = 0; - - assert(ret); - assert(string); - - for (;;) { - _cleanup_free_ char *word = NULL; - struct in_addr *new_addresses; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in_addr)); - if (!new_addresses) - return -ENOMEM; - else - addresses = new_addresses; - - r = inet_pton(AF_INET, word, &(addresses[size])); - if (r <= 0) - continue; - - size++; - } - - *ret = size > 0 ? TAKE_PTR(addresses) : NULL; - - return size; -} - -void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, size_t size, bool *with_leading_space) { - assert(f); - assert(addresses); - assert(size); - - bool _space = false; - if (!with_leading_space) - with_leading_space = &_space; - - for (size_t i = 0; i < size; i++) { - char buffer[INET6_ADDRSTRLEN]; - - if (*with_leading_space) - fputc(' ', f); - fputs(inet_ntop(AF_INET6, addresses+i, buffer, sizeof(buffer)), f); - *with_leading_space = true; - } -} - -int deserialize_in6_addrs(struct in6_addr **ret, const char *string) { - _cleanup_free_ struct in6_addr *addresses = NULL; - int size = 0; - - assert(ret); - assert(string); - - for (;;) { - _cleanup_free_ char *word = NULL; - struct in6_addr *new_addresses; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - new_addresses = reallocarray(addresses, size + 1, sizeof(struct in6_addr)); - if (!new_addresses) - return -ENOMEM; - else - addresses = new_addresses; - - r = inet_pton(AF_INET6, word, &(addresses[size])); - if (r <= 0) - continue; - - size++; - } - - *ret = TAKE_PTR(addresses); - - return size; -} - -void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size) { - assert(f); - assert(key); - assert(routes); - assert(size); - - fprintf(f, "%s=", key); - - for (size_t i = 0; i < size; i++) { - char sbuf[INET_ADDRSTRLEN]; - struct in_addr dest, gw; - uint8_t length; - - assert_se(sd_dhcp_route_get_destination(routes[i], &dest) >= 0); - assert_se(sd_dhcp_route_get_gateway(routes[i], &gw) >= 0); - assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &length) >= 0); - - fprintf(f, "%s/%" PRIu8, inet_ntop(AF_INET, &dest, sbuf, sizeof sbuf), length); - fprintf(f, ",%s%s", inet_ntop(AF_INET, &gw, sbuf, sizeof sbuf), i < size - 1 ? " ": ""); - } - - fputs("\n", f); -} - -int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string) { - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - size_t size = 0, allocated = 0; - - assert(ret); - assert(ret_size); - assert(ret_allocated); - assert(string); - - /* WORD FORMAT: dst_ip/dst_prefixlen,gw_ip */ - for (;;) { - _cleanup_free_ char *word = NULL; - char *tok, *tok_end; - unsigned n; - int r; - - r = extract_first_word(&string, &word, NULL, 0); - if (r < 0) - return r; - if (r == 0) - break; - - if (!GREEDY_REALLOC(routes, allocated, size + 1)) - return -ENOMEM; - - tok = word; - - /* get the subnet */ - tok_end = strchr(tok, '/'); - if (!tok_end) - continue; - *tok_end = '\0'; - - r = inet_aton(tok, &routes[size].dst_addr); - if (r == 0) - continue; - - tok = tok_end + 1; - - /* get the prefixlen */ - tok_end = strchr(tok, ','); - if (!tok_end) - continue; - - *tok_end = '\0'; - - r = safe_atou(tok, &n); - if (r < 0 || n > 32) - continue; - - routes[size].dst_prefixlen = (uint8_t) n; - tok = tok_end + 1; - - /* get the gateway */ - r = inet_aton(tok, &routes[size].gw_addr); - if (r == 0) - continue; - - size++; - } - - *ret_size = size; - *ret_allocated = allocated; - *ret = TAKE_PTR(routes); - - return 0; -} - -int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size) { - _cleanup_free_ char *hex_buf = NULL; - - assert(f); - assert(key); - assert(data); - - hex_buf = hexmem(data, size); - if (!hex_buf) - return -ENOMEM; - - fprintf(f, "%s=%s\n", key, hex_buf); - - return 0; -} diff --git a/src/systemd/src/libsystemd-network/network-internal.h b/src/systemd/src/libsystemd-network/network-internal.h deleted file mode 100644 index 1959474e..00000000 --- a/src/systemd/src/libsystemd-network/network-internal.h +++ /dev/null @@ -1,74 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ -#pragma once - -#include <linux/nl80211.h> -#include <stdbool.h> - -#include "sd-device.h" -#include "sd-dhcp-lease.h" - -#include "conf-parser.h" -#include "set.h" -#include "strv.h" - -#define LINK_BRIDGE_PORT_PRIORITY_INVALID 128 -#define LINK_BRIDGE_PORT_PRIORITY_MAX 63 - -#if 0 /* NM_IGNORED */ -bool net_match_config(Set *match_mac, - Set *match_permanent_mac, - char * const *match_paths, - char * const *match_drivers, - char * const *match_iftypes, - char * const *match_names, - char * const *match_property, - char * const *match_wifi_iftype, - char * const *match_ssid, - Set *match_bssid, - sd_device *device, - const struct ether_addr *dev_mac, - const struct ether_addr *dev_permanent_mac, - const char *dev_driver, - unsigned short dev_iftype, - const char *dev_name, - char * const *alternative_names, - enum nl80211_iftype dev_wifi_iftype, - const char *dev_ssid, - const struct ether_addr *dev_bssid); - -CONFIG_PARSER_PROTOTYPE(config_parse_net_condition); -CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr); -CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs); -CONFIG_PARSER_PROTOTYPE(config_parse_match_strv); -CONFIG_PARSER_PROTOTYPE(config_parse_match_ifnames); -CONFIG_PARSER_PROTOTYPE(config_parse_match_property); -CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); -CONFIG_PARSER_PROTOTYPE(config_parse_bridge_port_priority); - -int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *result); -const char *net_get_name_persistent(sd_device *device); -#endif /* NM_IGNORED */ - -size_t serialize_in_addrs(FILE *f, - const struct in_addr *addresses, - size_t size, - bool *with_leading_space, - bool (*predicate)(const struct in_addr *addr)); -int deserialize_in_addrs(struct in_addr **addresses, const char *string); -void serialize_in6_addrs(FILE *f, const struct in6_addr *addresses, - size_t size, - bool *with_leading_space); -int deserialize_in6_addrs(struct in6_addr **addresses, const char *string); - -/* don't include "dhcp-lease-internal.h" as it causes conflicts between netinet/ip.h and linux/ip.h */ -struct sd_dhcp_route; -struct sd_dhcp_lease; - -void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); -int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); - -/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ -int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); - -int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); -int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); diff --git a/src/tests/test-l3cfg.c b/src/tests/test-l3cfg.c deleted file mode 100644 index d55dcfbc..00000000 --- a/src/tests/test-l3cfg.c +++ /dev/null @@ -1,362 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ - -#include "nm-default.h" - -#include "nm-l3cfg.h" -#include "nm-netns.h" -#include "platform/nm-platform.h" - -#include "platform/tests/test-common.h" - -/*****************************************************************************/ - -typedef struct { - int test_idx; - NMPlatform * platform; - NMNetns * netns; - NMDedupMultiIndex *multiidx; - const char * ifname0; - const char * ifname1; - NMPLinkAddress hwaddr0; - NMPLinkAddress hwaddr1; - int ifindex0; - int ifindex1; -} TestFixture1; - -static const TestFixture1 * -_test_fixture_1_setup(TestFixture1 *f, int test_idx) -{ - const NMPlatformLink *l0; - const NMPlatformLink *l1; - - g_assert_cmpint(test_idx, >, 0); - g_assert_cmpint(f->test_idx, ==, 0); - - f->test_idx = test_idx; - - f->ifname0 = "nm-test-veth0"; - f->ifname1 = "nm-test-veth1"; - - f->platform = g_object_ref(NM_PLATFORM_GET); - f->multiidx = nm_dedup_multi_index_ref(nm_platform_get_multi_idx(f->platform)); - f->netns = nm_netns_new(f->platform); - - l0 = nmtstp_link_veth_add(f->platform, -1, f->ifname0, f->ifname1); - l1 = nmtstp_link_get_typed(f->platform, -1, f->ifname1, NM_LINK_TYPE_VETH); - - f->ifindex0 = l0->ifindex; - f->hwaddr0 = l0->l_address; - - f->ifindex1 = l1->ifindex; - f->hwaddr1 = l1->l_address; - - g_assert(nm_platform_link_set_up(f->platform, f->ifindex0, NULL)); - g_assert(nm_platform_link_set_up(f->platform, f->ifindex1, NULL)); - - return f; -} - -static void -_test_fixture_1_teardown(TestFixture1 *f) -{ - g_assert(f); - - if (f->test_idx == 0) - return; - - _LOGD("test teatdown"); - - nmtstp_link_delete(f->platform, -1, f->ifindex0, f->ifname0, TRUE); - g_assert(!nm_platform_link_get(f->platform, f->ifindex0)); - g_assert(!nm_platform_link_get(f->platform, f->ifindex1)); - g_assert(!nm_platform_link_get_by_ifname(f->platform, f->ifname0)); - g_assert(!nm_platform_link_get_by_ifname(f->platform, f->ifname1)); - - g_object_unref(f->netns); - g_object_unref(f->platform); - nm_dedup_multi_index_unref(f->multiidx); - - *f = (TestFixture1){ - .test_idx = 0, - }; -} - -/*****************************************************************************/ - -typedef enum { - TEST_L3CFG_NOTIFY_TYPE_NONE, - TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL, - TEST_L3CFG_NOTIFY_TYPE_COMMIT_1, - TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1, -} TestL3cfgNotifyType; - -typedef struct { - const TestFixture1 *f; - - TestL3cfgNotifyType notify_type; - guint post_commit_event_count; - guint general_event_count; - union { - struct { - int cb_count; - bool expected_probe_result : 1; - } wait_for_acd_ready_1; - } notify_data; -} TestL3cfgData; - -static void -_test_l3cfg_data_set_notify_type(TestL3cfgData *tdata, TestL3cfgNotifyType notify_type) -{ - g_assert(tdata); - - tdata->notify_type = notify_type; - tdata->post_commit_event_count = 0; - tdata->general_event_count = 0; - memset(&tdata->notify_data, 0, sizeof(tdata->notify_data)); -} - -static void -_test_l3cfg_signal_notify(NML3Cfg * l3cfg, - const NML3ConfigNotifyData *notify_data, - TestL3cfgData * tdata) -{ - g_assert(NM_IS_L3CFG(l3cfg)); - g_assert(tdata); - g_assert(notify_data); - g_assert(_NM_INT_NOT_NEGATIVE(notify_data->notify_type)); - g_assert(notify_data->notify_type < _NM_L3_CONFIG_NOTIFY_TYPE_NUM); - - if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE) - g_assert(notify_data->platform_change_on_idle.obj_type_flags != 0u); - else if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE) { - g_assert(NMP_OBJECT_IS_VALID(notify_data->platform_change.obj)); - g_assert(notify_data->platform_change.change_type != 0); - } - - switch (tdata->notify_type) { - case TEST_L3CFG_NOTIFY_TYPE_NONE: - g_assert_not_reached(); - break; - case TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL: - if (NM_IN_SET(notify_data->notify_type, - NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, - NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)) - return; - g_assert_not_reached(); - return; - case TEST_L3CFG_NOTIFY_TYPE_COMMIT_1: - g_assert_cmpint(tdata->post_commit_event_count, ==, 0); - switch (notify_data->notify_type) { - case NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT: - tdata->post_commit_event_count++; - return; - case NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED: - switch (tdata->f->test_idx) { - case 2: - nmtst_assert_ip4_address(notify_data->acd_completed.addr, "192.167.133.45"); - g_assert(notify_data->acd_completed.probe_result); - g_assert(tdata->general_event_count == 0); - tdata->general_event_count++; - return; - default: - g_assert_not_reached(); - return; - } - case NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE: - return; - default: - g_assert_not_reached(); - return; - } - case TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1: - if (NM_IN_SET(notify_data->notify_type, - NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE, - NM_L3_CONFIG_NOTIFY_TYPE_PLATFORM_CHANGE_ON_IDLE)) - return; - if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_ACD_COMPLETED) { - g_assert(tdata->notify_data.wait_for_acd_ready_1.cb_count == 0); - tdata->notify_data.wait_for_acd_ready_1.cb_count++; - return; - } - if (notify_data->notify_type == NM_L3_CONFIG_NOTIFY_TYPE_POST_COMMIT) { - g_assert(tdata->notify_data.wait_for_acd_ready_1.cb_count == 1); - tdata->notify_data.wait_for_acd_ready_1.cb_count++; - nmtstp_platform_ip_addresses_assert(tdata->f->platform, - tdata->f->ifindex0, - TRUE, - TRUE, - TRUE, - "192.167.133.45", - "1:2:3:4::45"); - return; - } - g_assert_not_reached(); - return; - } - - g_assert_not_reached(); -} - -static void -test_l3cfg(gconstpointer test_data) -{ - nm_auto(_test_fixture_1_teardown) TestFixture1 test_fixture = {}; - const TestFixture1 * f; - NML3CfgCommitTypeHandle * commit_type_1; - NML3CfgCommitTypeHandle * commit_type_2; - gs_unref_object NML3Cfg *l3cfg0 = NULL; - nm_auto_unref_l3cd const NML3ConfigData *l3cd_a = NULL; - guint32 acd_timeout_msec = 0; - TestL3cfgData tdata_stack = { - .f = NULL, - }; - TestL3cfgData *const tdata = &tdata_stack; - - _LOGD("test start (/l3cfg/%d)", GPOINTER_TO_INT(test_data)); - - if (nmtst_test_quick()) { - gs_free char *msg = - g_strdup_printf("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", - g_get_prgname() ?: "test-l3cfg"); - - g_test_skip(msg); - return; - } - - f = _test_fixture_1_setup(&test_fixture, GPOINTER_TO_INT(test_data)); - - tdata->f = f; - - l3cfg0 = nm_netns_access_l3cfg(f->netns, f->ifindex0); - g_assert(NM_IS_L3CFG(l3cfg0)); - - g_signal_connect(l3cfg0, NM_L3CFG_SIGNAL_NOTIFY, G_CALLBACK(_test_l3cfg_signal_notify), tdata); - - commit_type_1 = nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL); - - if ((nmtst_get_rand_uint32() % 4u) != 0) { - commit_type_2 = - nm_l3cfg_commit_type_register(l3cfg0, - nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, - NM_L3_CFG_COMMIT_TYPE_ASSUME, - NM_L3_CFG_COMMIT_TYPE_UPDATE), - NULL); - } else - commit_type_2 = NULL; - - switch (f->test_idx) { - case 1: - break; - case 2: - case 3: - { - nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; - - l3cd = nm_l3_config_data_new(f->multiidx, f->ifindex0); - - nm_l3_config_data_add_address_4( - l3cd, - NM_PLATFORM_IP4_ADDRESS_INIT(.address = nmtst_inet4_from_string("192.167.133.45"), - .peer_address = nmtst_inet4_from_string("192.167.133.45"), - .plen = 24, )); - - nm_l3_config_data_add_address_6( - l3cd, - NM_PLATFORM_IP6_ADDRESS_INIT(.address = *nmtst_inet6_from_string("1:2:3:4::45"), - .plen = 64, )); - - if (nmtst_get_rand_bool()) - nm_l3_config_data_seal(l3cd); - l3cd_a = g_steal_pointer(&l3cd); - break; - } - } - - acd_timeout_msec = (f->test_idx == 3) ? 2000u : 0u; - - if (l3cd_a) { - nm_l3cfg_add_config(l3cfg0, - GINT_TO_POINTER('a'), - nmtst_get_rand_bool(), - l3cd_a, - 'a', - 0, - 0, - NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP4, - NM_PLATFORM_ROUTE_METRIC_DEFAULT_IP6, - 0, - 0, - acd_timeout_msec, - NM_L3_CONFIG_MERGE_FLAGS_NONE); - } - - nm_l3_config_data_log(nm_l3cfg_get_combined_l3cd(l3cfg0, FALSE), - "test", - "platform-test: l3cfg0: ", - LOGL_DEBUG, - LOGD_PLATFORM); - - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_COMMIT_1); - nm_l3cfg_commit(l3cfg0, NM_L3_CFG_COMMIT_TYPE_REAPPLY); - g_assert_cmpint(tdata->post_commit_event_count, ==, 1); - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); - - nmtstp_platform_ip_addresses_assert(tdata->f->platform, - tdata->f->ifindex0, - TRUE, - TRUE, - TRUE, - NM_IN_SET(f->test_idx, 2) ? "192.167.133.45" : NULL, - NM_IN_SET(f->test_idx, 2, 3) ? "1:2:3:4::45" : NULL); - - if (NM_IN_SET(f->test_idx, 1, 2)) { - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_IDLE_ASSERT_NO_SIGNAL); - _LOGT("poll 1 start"); - nmtst_main_context_iterate_until(NULL, nmtst_get_rand_uint32() % 5000u, FALSE); - _LOGT("poll 1 end"); - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); - } - - if (NM_IN_SET(f->test_idx, 3)) { - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_WAIT_FOR_ACD_READY_1); - tdata->notify_data.wait_for_acd_ready_1.expected_probe_result = TRUE; - _LOGT("poll 2 start"); - nmtst_main_context_iterate_until(NULL, 2500u + (nmtst_get_rand_uint32() % 4000u), FALSE); - _LOGT("poll 2 end"); - g_assert_cmpint(tdata->notify_data.wait_for_acd_ready_1.cb_count, ==, 2); - _test_l3cfg_data_set_notify_type(tdata, TEST_L3CFG_NOTIFY_TYPE_NONE); - } - - g_signal_handlers_disconnect_by_func(l3cfg0, G_CALLBACK(_test_l3cfg_signal_notify), tdata); - - nm_l3cfg_commit_type_unregister(l3cfg0, commit_type_1); - nm_l3cfg_commit_type_unregister(l3cfg0, commit_type_2); - - if ((nmtst_get_rand_uint32() % 3) == 0) - _test_fixture_1_teardown(&test_fixture); - - nm_l3cfg_remove_config_all(l3cfg0, GINT_TO_POINTER('a'), FALSE); - - if ((nmtst_get_rand_uint32() % 3) == 0) - _test_fixture_1_teardown(&test_fixture); - - _LOGD("test end (/l3cfg/%d)", f->test_idx); -} - -/*****************************************************************************/ - -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_data_func("/l3cfg/1", GINT_TO_POINTER(1), test_l3cfg); - g_test_add_data_func("/l3cfg/2", GINT_TO_POINTER(2), test_l3cfg); - g_test_add_data_func("/l3cfg/3", GINT_TO_POINTER(3), test_l3cfg); -} |